aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-08-23 19:25:47 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-08-23 19:25:47 +0000
commit03635e3cb4929139788051802baf44b646fe576f (patch)
tree5ebec49ee52f0f136f147d0cfa11c1b5e7a9a617
parent43974f5c23dc769d9d9306f845b451665cc99ab3 (diff)
downloadpaludis-03635e3cb4929139788051802baf44b646fe576f.tar.gz
paludis-03635e3cb4929139788051802baf44b646fe576f.tar.xz
Add archtool (temporary name, until we come up with something better)
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/archtool/Makefile.am69
-rw-r--r--src/archtool/archtool.cc214
-rw-r--r--src/archtool/archtool_environment.cc68
-rw-r--r--src/archtool/archtool_environment.hh42
-rw-r--r--src/archtool/command_line.cc99
-rw-r--r--src/archtool/command_line.hh97
-rw-r--r--src/archtool/find_stable_candidates.cc207
-rw-r--r--src/archtool/find_stable_candidates.hh27
-rw-r--r--src/archtool/find_stable_candidates.sr12
-rwxr-xr-xsrc/archtool/find_stable_candidates_TEST18
-rwxr-xr-xsrc/archtool/find_stable_candidates_TEST_cleanup.sh11
-rwxr-xr-xsrc/archtool/find_stable_candidates_TEST_setup.sh71
-rwxr-xr-xsrc/archtool/help_TEST4
-rw-r--r--src/archtool/keywords_graph.cc165
-rw-r--r--src/archtool/keywords_graph.hh27
-rw-r--r--src/archtool/man_archtool.cc36
-rwxr-xr-xsrc/archtool/version_TEST3
19 files changed, 1172 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index d7644fb..7c16790 100644
--- a/configure.ac
+++ b/configure.ac
@@ -519,6 +519,7 @@ AC_OUTPUT(
src/gtkpaludis/vtemm/converts/Makefile
src/gtkpaludis/vtemm/defs/Makefile
src/qualudis/Makefile
+ src/archtool/Makefile
test/Makefile
)
dnl }}}
diff --git a/src/Makefile.am b/src/Makefile.am
index b1fde1f..fe09f67 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = paludis gtkpaludis qualudis
+SUBDIRS = paludis gtkpaludis qualudis archtool
CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/archtool/Makefile.am b/src/archtool/Makefile.am
new file mode 100644
index 0000000..886545b
--- /dev/null
+++ b/src/archtool/Makefile.am
@@ -0,0 +1,69 @@
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+SUBDIRS = .
+
+bin_PROGRAMS = archtool
+noinst_PROGRAMS = man-archtool
+
+man_MANS = archtool.1
+
+archtool.1 : man-archtool
+ ./man-archtool | tee $@ | sed -e 's/^/ /'
+
+man_archtool_SOURCES = \
+ man_archtool.cc \
+ command_line.hh \
+ command_line.cc
+
+man_archtool_LDADD = \
+ $(top_builddir)/paludis/args/libpaludisargs.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+archtool_SOURCES = \
+ command_line.hh command_line.cc \
+ find_stable_candidates.hh find_stable_candidates.cc \
+ keywords_graph.hh keywords_graph.cc \
+ archtool_environment.hh archtool_environment.cc \
+ archtool.cc
+
+archtool_LDADD = \
+ $(top_builddir)/paludis/tasks/libpaludistasks.a \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/args/libpaludisargs.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+TESTS_ENVIRONMENT = env \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_NO_GLOBAL_HOOKS="yes" \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/ebuild/utils/canonicalise $(top_srcdir)/ebuild/`" \
+ PALUDIS_EBUILD_DIR_FALLBACK="`$(top_srcdir)/ebuild/utils/canonicalise $(top_builddir)/ebuild/`" \
+ PALUDIS_REPOSITORY_SO_DIR="`$(top_srcdir)/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories`" \
+ SYSCONFDIR="$(sysconfdir)" \
+ bash $(top_srcdir)/test/run_test.sh bash
+
+TESTS = version_TEST help_TEST find_stable_candidates_TEST
+
+EXTRA_DIST = \
+ $(man_MANS) \
+ $(TESTS) \
+ find_stable_candidates-sr.hh find_stable_candidates-sr.cc \
+ find_stable_candidates_TEST_setup.sh find_stable_candidates_TEST_cleanup.sh
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = $(man_MANS) find_stable_candidates-sr.hh find_stable_candidates-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+BUILT_SOURCES = find_stable_candidates-sr.hh find_stable_candidates-sr.cc
+
+find_stable_candidates-sr.hh : find_stable_candidates.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/find_stable_candidates.sr > $@
+
+find_stable_candidates-sr.cc : find_stable_candidates.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/find_stable_candidates.sr > $@
+
diff --git a/src/archtool/archtool.cc b/src/archtool/archtool.cc
new file mode 100644
index 0000000..dcd146a
--- /dev/null
+++ b/src/archtool/archtool.cc
@@ -0,0 +1,214 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command_line.hh"
+#include "find_stable_candidates.hh"
+#include "keywords_graph.hh"
+#include "archtool_environment.hh"
+
+#include <paludis/about.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/fs_entry.hh>
+#include <iostream>
+
+using namespace paludis;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+namespace
+{
+ FSEntry
+ get_location_and_add_filters()
+ {
+ Context context("When determining tree location:");
+
+ if (CommandLine::get_instance()->a_repository_directory.specified())
+ return FSEntry(CommandLine::get_instance()->a_repository_directory.argument());
+
+ if ((FSEntry::cwd() / "profiles").is_directory())
+ return FSEntry::cwd();
+ if ((FSEntry::cwd().dirname() / "profiles").is_directory())
+ {
+ CommandLine::get_instance()->a_category.add_argument(FSEntry::cwd().basename());
+ CommandLine::get_instance()->a_category.set_specified(true);
+ return FSEntry::cwd().dirname();
+ }
+ if ((FSEntry::cwd().dirname().dirname() / "profiles").is_directory())
+ {
+ CommandLine::get_instance()->a_package.add_argument(FSEntry::cwd().basename());
+ CommandLine::get_instance()->a_package.set_specified(true);
+ CommandLine::get_instance()->a_category.add_argument(FSEntry::cwd().dirname().basename());
+ CommandLine::get_instance()->a_category.set_specified(true);
+ return FSEntry::cwd().dirname().dirname();
+ }
+
+ throw ConfigurationError("Cannot find tree location (try specifying --repository-directory)");
+ }
+
+ void display_version()
+ {
+ cout << "archtool " << PALUDIS_VERSION_MAJOR << "."
+ << PALUDIS_VERSION_MINOR << "." << PALUDIS_VERSION_MICRO;
+ if (! std::string(PALUDIS_SUBVERSION_REVISION).empty())
+ cout << " svn " << PALUDIS_SUBVERSION_REVISION;
+ cout << endl << endl;
+ cout << "Built by " << PALUDIS_BUILD_USER << "@" << PALUDIS_BUILD_HOST
+ << " on " << PALUDIS_BUILD_DATE << endl;
+ cout << "CXX: " << PALUDIS_BUILD_CXX
+#if defined(__ICC)
+ << " " << __ICC
+#elif defined(__VERSION__)
+ << " " << __VERSION__
+#endif
+ << endl;
+ cout << "CXXFLAGS: " << PALUDIS_BUILD_CXXFLAGS << endl;
+ cout << "LDFLAGS: " << PALUDIS_BUILD_LDFLAGS << endl;
+ cout << "DATADIR: " << DATADIR << endl;
+ cout << "LIBDIR: " << LIBDIR << endl;
+ cout << "LIBEXECDIR: " << LIBEXECDIR << endl;
+ cout << "SYSCONFDIR: " << SYSCONFDIR << endl;
+ cout << "stdlib: "
+#if defined(__GLIBCXX__)
+# define XSTRINGIFY(x) #x
+# define STRINGIFY(x) XSTRINGIFY(x)
+ << "GNU libstdc++ " << STRINGIFY(__GLIBCXX__)
+#endif
+ << endl;
+ }
+
+ struct DoVersion
+ {
+ };
+}
+
+int
+main(int argc, char *argv[])
+{
+ Context context("In program " + join(argv, argv + argc, " ") + ":");
+
+ try
+ {
+ CommandLine::get_instance()->run(argc, argv);
+
+ if (CommandLine::get_instance()->a_help.specified())
+ throw DoHelp();
+
+ if (CommandLine::get_instance()->a_version.specified())
+ throw DoVersion();
+
+ if (! CommandLine::get_instance()->a_log_level.specified())
+ Log::get_instance()->set_log_level(ll_qa);
+ else if (CommandLine::get_instance()->a_log_level.argument() == "debug")
+ Log::get_instance()->set_log_level(ll_debug);
+ else if (CommandLine::get_instance()->a_log_level.argument() == "qa")
+ Log::get_instance()->set_log_level(ll_qa);
+ else if (CommandLine::get_instance()->a_log_level.argument() == "warning")
+ Log::get_instance()->set_log_level(ll_warning);
+ else if (CommandLine::get_instance()->a_log_level.argument() == "silent")
+ Log::get_instance()->set_log_level(ll_silent);
+ else
+ throw DoHelp("bad value for --log-level");
+
+ if (1 != (
+ CommandLine::get_instance()->a_find_stable_candidates.specified() +
+ CommandLine::get_instance()->a_keywords_graph.specified()))
+ throw DoHelp("you should specify exactly one action");
+
+ ArchtoolEnvironment env(get_location_and_add_filters());
+
+ if (CommandLine::get_instance()->a_find_stable_candidates.specified())
+ {
+ if (1 != std::distance(CommandLine::get_instance()->begin_parameters(),
+ CommandLine::get_instance()->end_parameters()))
+ throw DoHelp("find-stable-candidates action takes exactly one parameter (the target arch)");
+
+ do_find_stable_candidates(env);
+ return EXIT_SUCCESS;
+ }
+
+ if (CommandLine::get_instance()->a_keywords_graph.specified())
+ {
+ if (CommandLine::get_instance()->begin_parameters() !=
+ CommandLine::get_instance()->end_parameters())
+ throw DoHelp("keywords-graph action takes no parameters");
+
+ do_keywords_graph(env);
+ return EXIT_SUCCESS;
+ }
+
+ throw InternalError(__PRETTY_FUNCTION__, "no action?");
+ }
+ catch (const DoVersion &)
+ {
+ display_version();
+ cout << endl;
+ cout << "Paludis comes with ABSOLUTELY NO WARRANTY. Paludis is free software, and you" << endl;
+ cout << "are welcome to redistribute it under the terms of the GNU General Public" << endl;
+ cout << "License, version 2." << endl;
+
+ return EXIT_SUCCESS;
+ }
+ catch (const paludis::args::ArgsError & e)
+ {
+ cerr << "Usage error: " << e.message() << endl;
+ cerr << "Try " << argv[0] << " --help" << endl;
+ return EXIT_FAILURE;
+ }
+ catch (const DoHelp & h)
+ {
+ if (h.message.empty())
+ {
+ cout << "Usage: " << argv[0] << " [options]" << endl;
+ cout << endl;
+ cout << *CommandLine::get_instance();
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ cerr << "Usage error: " << h.message << endl;
+ cerr << "Try " << argv[0] << " --help" << endl;
+ return EXIT_FAILURE;
+ }
+ }
+ catch (const Exception & e)
+ {
+ cout << endl;
+ cerr << "Unhandled exception:" << endl
+ << " * " << e.backtrace("\n * ")
+ << e.message() << " (" << e.what() << ")" << endl;
+ return EXIT_FAILURE;
+ }
+ catch (const std::exception & e)
+ {
+ cout << endl;
+ cerr << "Unhandled exception:" << endl
+ << " * " << e.what() << endl;
+ return EXIT_FAILURE;
+ }
+ catch (...)
+ {
+ cout << endl;
+ cerr << "Unhandled exception:" << endl
+ << " * Unknown exception type. Ouch..." << endl;
+ return EXIT_FAILURE;
+ }
+}
+
diff --git a/src/archtool/archtool_environment.cc b/src/archtool/archtool_environment.cc
new file mode 100644
index 0000000..fbe97ea
--- /dev/null
+++ b/src/archtool/archtool_environment.cc
@@ -0,0 +1,68 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "archtool_environment.hh"
+#include <paludis/util/collection_concrete.hh>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<ArchtoolEnvironment> :
+ InternalCounted<Implementation<ArchtoolEnvironment> >
+ {
+ const FSEntry top_level_dir;
+ PackageDatabase::Pointer db;
+
+ Implementation(Environment * const env, const FSEntry & d) :
+ top_level_dir(d),
+ db(new PackageDatabase(env))
+ {
+ }
+ };
+}
+
+ArchtoolEnvironment::ArchtoolEnvironment(const FSEntry & dir) :
+ PrivateImplementationPattern<ArchtoolEnvironment>(
+ new Implementation<ArchtoolEnvironment>(this, dir)),
+ Environment(_imp->db)
+{
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+
+ keys->insert("format", "portage");
+ keys->insert("location", stringify(_imp->top_level_dir));
+ keys->insert("profiles", stringify(_imp->top_level_dir / "profiles" / "base"));
+
+ _imp->db->add_repository(
+ RepositoryMaker::get_instance()->find_maker("portage")(this,
+ _imp->db.raw_pointer(), keys));
+}
+
+ArchtoolEnvironment::~ArchtoolEnvironment()
+{
+}
+
+std::string
+ArchtoolEnvironment::paludis_command() const
+{
+ return "false";
+}
+
diff --git a/src/archtool/archtool_environment.hh b/src/archtool/archtool_environment.hh
new file mode 100644
index 0000000..31e0f24
--- /dev/null
+++ b/src/archtool/archtool_environment.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_ARCHTOOL_ARCHTOOL_ENVIRONMENT_HH
+#define PALUDIS_GUARD_SRC_ARCHTOOL_ARCHTOOL_ENVIRONMENT_HH 1
+
+#include <paludis/environment.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class ArchtoolEnvironment :
+ private PrivateImplementationPattern<ArchtoolEnvironment>,
+ public Environment
+ {
+ public:
+ ArchtoolEnvironment(const FSEntry & dir);
+
+ virtual ~ArchtoolEnvironment();
+
+ virtual std::string paludis_command() const;
+ };
+}
+
+#endif
diff --git a/src/archtool/command_line.cc b/src/archtool/command_line.cc
new file mode 100644
index 0000000..75e611d
--- /dev/null
+++ b/src/archtool/command_line.cc
@@ -0,0 +1,99 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command_line.hh"
+
+CommandLine::CommandLine() :
+ ArgsHandler(),
+
+ action_args(this, "Actions",
+ "Selects which basic action to perform. Exactly one action should "
+ "be specified."),
+
+ a_find_stable_candidates(&action_args,
+ "find-stable-candidates", 's', "Search for stable package candidates"),
+ a_keywords_graph(&action_args,
+ "keyword-graph", 'k', "Display KEYWORDS graphically"),
+ a_version(&action_args,
+ "version", 'V', "Display program version"),
+ a_help(&action_args,
+ "help", 'h', "Display program help"),
+
+ general_args(this, "General options",
+ "Options which are relevant for most or all actions."),
+ a_log_level(&general_args, "log-level", '\0', "Specify the log level",
+ paludis::args::EnumArg::EnumArgOptions("debug", "Show debug output (noisy)")
+ ("qa", "Show QA messages and warnings only")
+ ("warning", "Show warnings only")
+ ("silent", "Suppress all log messages"),
+ "qa"),
+ a_repository_directory(&general_args, "repository-dir", 'D',
+ "Where to find the repository (default: detected from ./ or ../ or ../..)"),
+ a_category(&general_args, "category", 'C',
+ "Matches with this category name only"),
+ a_package(&general_args, "package", 'P',
+ "Matches with this package name only")
+{
+ add_usage_line("--find-stable-candidates [ --repository-dir /path ] "
+ "[ --category app-misc --category sys-apps ... ] "
+ "[ --package foo --package fnord ... ] "
+ "arch");
+ add_usage_line("--keywords-graph [ --repository-dir /path ] "
+ "[ --category app-misc --category sys-apps ... ] "
+ "[ --package foo --package fnord ... ]"),
+
+ add_usage_line("--version");
+ add_usage_line("--help");
+
+ add_enviromnent_variable("PALUDIS_EBUILD_DIR", "Where to look for ebuild.bash and related "
+ "utilities.");
+ add_enviromnent_variable("PALUDIS_REPOSITORY_SO_DIR", "Where to look for repository .so "
+ "files.");
+}
+
+std::string
+CommandLine::app_name() const
+{
+ return "archtool";
+}
+
+std::string
+CommandLine::app_synopsis() const
+{
+ return "A tool for arch teams";
+}
+
+std::string
+CommandLine::app_description() const
+{
+ return
+ "archtool provides a number of utilities that may be useful for arch teams."
+ "\n\n"
+ "The --repository-dir switch can be used to tell archtool where to find "
+ "the repository. If this switch is not used, archtool will check the current "
+ "directory, the parent directory and the parent's parent directory for "
+ "something resembling a profile root. If run inside a package or category "
+ "directory, filtering in the style of --package and --category is carried "
+ "out automatically for the current package or category.";
+}
+
+CommandLine::~CommandLine()
+{
+}
+
diff --git a/src/archtool/command_line.hh b/src/archtool/command_line.hh
new file mode 100644
index 0000000..a2ebed5
--- /dev/null
+++ b/src/archtool/command_line.hh
@@ -0,0 +1,97 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_ARCHTOOL_COMMAND_LINE_HH
+#define PALUDIS_GUARD_SRC_ARCHTOOL_COMMAND_LINE_HH 1
+
+#include <paludis/args/args.hh>
+#include <paludis/util/instantiation_policy.hh>
+
+/** \file
+ * Declarations for the CommandLine class.
+ */
+
+/**
+ * Our command line.
+ */
+class CommandLine :
+ public paludis::args::ArgsHandler,
+ public paludis::InstantiationPolicy<CommandLine, paludis::instantiation_method::SingletonAsNeededTag>
+{
+ friend class paludis::InstantiationPolicy<CommandLine, paludis::instantiation_method::SingletonAsNeededTag>;
+
+ private:
+ /// Constructor.
+ CommandLine();
+
+ /// Destructor.
+ ~CommandLine();
+
+ public:
+ ///\name Program information
+ ///\{
+
+ virtual std::string app_name() const;
+ virtual std::string app_synopsis() const;
+ virtual std::string app_description() const;
+
+ ///\}
+
+ /// \name Action arguments
+ ///{
+
+ /// Action arguments.
+ paludis::args::ArgsGroup action_args;
+
+ paludis::args::SwitchArg a_find_stable_candidates;
+ paludis::args::SwitchArg a_keywords_graph;
+
+ paludis::args::SwitchArg a_version;
+ paludis::args::SwitchArg a_help;
+
+ /// \name General arguments
+ ///{
+
+ /// General arguments.
+ paludis::args::ArgsGroup general_args;
+
+ /// --log-level
+ paludis::args::EnumArg a_log_level;
+
+ paludis::args::StringArg a_repository_directory;
+ paludis::args::StringSetArg a_category;
+ paludis::args::StringSetArg a_package;
+
+ ///}
+};
+
+/**
+ * Show the help message.
+ */
+struct DoHelp
+{
+ const std::string message;
+
+ DoHelp(const std::string & m = "") :
+ message(m)
+ {
+ }
+};
+
+#endif
diff --git a/src/archtool/find_stable_candidates.cc b/src/archtool/find_stable_candidates.cc
new file mode 100644
index 0000000..82e1eb6
--- /dev/null
+++ b/src/archtool/find_stable_candidates.cc
@@ -0,0 +1,207 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "find_stable_candidates.hh"
+#include "command_line.hh"
+
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/compare.hh>
+
+#include <set>
+#include <map>
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+
+using namespace paludis;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+namespace
+{
+
+#include "find_stable_candidates-sr.hh"
+#include "find_stable_candidates-sr.cc"
+
+ static const int col_width_package = 30;
+ static const int col_width_our_version = 20;
+ static const int col_width_best_version = 20;
+
+ void
+ write_repository_header(const KeywordName & keyword, const RepositoryName & repo)
+ {
+ std::string s("Stable candidates for '" + stringify(repo) + "' on '"
+ + stringify(keyword) + "'");
+ cout << std::string(s.length(), '=') << endl;
+ cout << s << endl;
+ cout << std::string(s.length(), '=') << endl;
+ cout << endl;
+
+ cout << std::left
+ << std::setw(col_width_package) << "category/package (:slot)"
+ << std::setw(col_width_our_version) << "our version"
+ << std::setw(col_width_best_version) << "best version"
+ << endl;
+
+ cout
+ << std::string(col_width_package - 1, '-') << " "
+ << std::string(col_width_our_version - 1, '-') << " "
+ << std::string(col_width_best_version - 1, '-') << " "
+ << endl;
+ }
+
+ struct IsStableKeyword
+ {
+ bool operator() (const KeywordName & k) const
+ {
+ return std::string::npos == std::string("-~").find(k.data().at(0));
+ }
+ };
+
+ void
+ write_package(const QualifiedPackageName & package, const SlotName & slot,
+ const VersionSpec & our_version, const VersionSpec & best_version)
+ {
+ static CategoryNamePart previous_category("not-on-a-boat");
+ if (package.category != previous_category)
+ {
+ cout << std::setw(col_width_package) << (stringify(package.category) + "/") << endl;
+ previous_category = package.category;
+ }
+
+ std::string p(stringify(package.package));
+ if (SlotName("0") != slot)
+ p += ":" + stringify(slot);
+ cout << " " << std::setw(col_width_package - 2) << p;
+
+ if (our_version != VersionSpec("0"))
+ cout << std::setw(col_width_our_version) << our_version;
+ else
+ cout << std::setw(col_width_our_version) << " ";
+ cout << std::setw(col_width_best_version) << best_version;
+ cout << endl;
+ }
+
+ void
+ check_one_package(const Environment &, const KeywordName & keyword,
+ const Repository & repo, const QualifiedPackageName & package)
+ {
+ /* determine whether we have any interesting versions, and pick out
+ * slots where we do. for slots, we map slot to a pair (best stable
+ * version for us, best stable version for anyone). */
+
+ bool is_interesting(false);
+ typedef std::map<SlotName, SlotsEntry> SlotsToVersions;
+ SlotsToVersions slots_to_versions;
+
+ VersionSpecCollection::ConstPointer versions(repo.version_specs(package));
+ for (VersionSpecCollection::Iterator v(versions->begin()), v_end(versions->end()) ;
+ v != v_end ; ++v)
+ {
+ VersionMetadata::ConstPointer metadata(repo.version_metadata(package, *v));
+ if (! metadata->get_ebuild_interface())
+ continue;
+
+ std::set<KeywordName> keywords;
+ WhitespaceTokeniser::get_instance()->tokenise(metadata->get_ebuild_interface()->keywords,
+ create_inserter<KeywordName>(std::inserter(keywords, keywords.end())));
+
+ if (keywords.end() != keywords.find(keyword))
+ {
+ is_interesting = true;
+
+ /* replace the entry */
+ slots_to_versions.erase(metadata->slot);
+ slots_to_versions.insert(std::make_pair(metadata->slot,
+ SlotsEntry(SlotsEntry::create()
+ .our_version(*v)
+ .best_version(VersionSpec("0")))));
+ }
+
+ if (keywords.end() != std::find_if(keywords.begin(), keywords.end(), IsStableKeyword()))
+ {
+ /* ensure that an entry exists */
+ slots_to_versions.insert(std::make_pair(metadata->slot,
+ SlotsEntry(SlotsEntry::create()
+ .our_version(VersionSpec("0"))
+ .best_version(*v))));
+
+ /* update the entry to mark our current version as the best
+ * version */
+ if (slots_to_versions.find(metadata->slot)->second.best_version <= *v)
+ slots_to_versions.find(metadata->slot)->second.best_version = *v;
+ }
+ }
+
+ if (! is_interesting)
+ return;
+
+ /* for each slot, if there's a higher stable version on another arch, flag it */
+ for (SlotsToVersions::const_iterator s(slots_to_versions.begin()),
+ s_end(slots_to_versions.end()) ; s != s_end ; ++s)
+ {
+ if (s->second.our_version >= s->second.best_version)
+ continue;
+
+ write_package(package, s->first, s->second.our_version, s->second.best_version);
+ }
+ }
+}
+
+void do_find_stable_candidates(const Environment & env)
+{
+ Context context("When performing find-stable-candidates action:");
+
+ KeywordName keyword(*CommandLine::get_instance()->begin_parameters());
+
+ for (IndirectIterator<PackageDatabase::RepositoryIterator, const Repository>
+ r(env.package_database()->begin_repositories()),
+ r_end(env.package_database()->end_repositories()) ; r != r_end ; ++r)
+ {
+ write_repository_header(keyword, r->name());
+
+ CategoryNamePartCollection::ConstPointer cat_names(r->category_names());
+ for (CategoryNamePartCollection::Iterator c(cat_names->begin()), c_end(cat_names->end()) ;
+ c != c_end ; ++c)
+ {
+ if (CommandLine::get_instance()->a_category.specified())
+ if (CommandLine::get_instance()->a_category.args_end() == std::find(
+ CommandLine::get_instance()->a_category.args_begin(),
+ CommandLine::get_instance()->a_category.args_end(),
+ stringify(*c)))
+ continue;
+
+ QualifiedPackageNameCollection::ConstPointer pkg_names(r->package_names(*c));
+ for (QualifiedPackageNameCollection::Iterator p(pkg_names->begin()), p_end(pkg_names->end()) ;
+ p != p_end ; ++p)
+ {
+ if (CommandLine::get_instance()->a_package.specified())
+ if (CommandLine::get_instance()->a_package.args_end() == std::find(
+ CommandLine::get_instance()->a_package.args_begin(),
+ CommandLine::get_instance()->a_package.args_end(),
+ stringify(p->package)))
+ continue;
+
+ check_one_package(env, keyword, *r, *p);
+ }
+ }
+ }
+}
+
diff --git a/src/archtool/find_stable_candidates.hh b/src/archtool/find_stable_candidates.hh
new file mode 100644
index 0000000..6e97b23
--- /dev/null
+++ b/src/archtool/find_stable_candidates.hh
@@ -0,0 +1,27 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_ARCHTOOL_FIND_STABLE_CANDIDATES_HH
+#define PALUDIS_GUARD_SRC_ARCHTOOL_FIND_STABLE_CANDIDATES_HH 1
+
+#include <paludis/environment.hh>
+
+void do_find_stable_candidates(const paludis::Environment & env);
+
+#endif
diff --git a/src/archtool/find_stable_candidates.sr b/src/archtool/find_stable_candidates.sr
new file mode 100644
index 0000000..9172a89
--- /dev/null
+++ b/src/archtool/find_stable_candidates.sr
@@ -0,0 +1,12 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_SlotsEntry()
+{
+ key our_version VersionSpec
+ key best_version VersionSpec
+
+ allow_named_args
+}
+
+
diff --git a/src/archtool/find_stable_candidates_TEST b/src/archtool/find_stable_candidates_TEST
new file mode 100755
index 0000000..9da4752
--- /dev/null
+++ b/src/archtool/find_stable_candidates_TEST
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+./archtool --find-stable-candidates -D find_stable_candidates_TEST_dir/ best | \
+ tee find_stable_candidates_TEST_dir/out1.txt
+
+if grep --silent '^ ' find_stable_candidates_TEST_dir/out1.txt ; then
+ echo "out1 failed" 1>&2
+ exit 127
+fi
+
+./archtool --find-stable-candidates -D find_stable_candidates_TEST_dir/ one | \
+ tee find_stable_candidates_TEST_dir/out2.txt
+
+if [[ $(grep --count '^ ' find_stable_candidates_TEST_dir/out2.txt ) != "1" ]] ; then
+ echo "out2 failed" 1>&2
+ exit 127
+fi
+
diff --git a/src/archtool/find_stable_candidates_TEST_cleanup.sh b/src/archtool/find_stable_candidates_TEST_cleanup.sh
new file mode 100755
index 0000000..1bdc7c1
--- /dev/null
+++ b/src/archtool/find_stable_candidates_TEST_cleanup.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d find_stable_candidates_TEST_dir ] ; then
+ rm -fr find_stable_candidates_TEST_dir
+else
+ true
+fi
+
+
+
diff --git a/src/archtool/find_stable_candidates_TEST_setup.sh b/src/archtool/find_stable_candidates_TEST_setup.sh
new file mode 100755
index 0000000..74a0a4a
--- /dev/null
+++ b/src/archtool/find_stable_candidates_TEST_setup.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir find_stable_candidates_TEST_dir || exit 1
+cd find_stable_candidates_TEST_dir || exit 1
+
+mkdir -p {eclass,distfiles,profiles/profile} || exit 1
+echo "test-repo-1" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+cat-three
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+
+mkdir cat-one
+mkdir cat-one/pkg-one
+cat <<"END" > cat-one/pkg-one/pkg-one-1.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="best one"
+END
+
+cat <<"END" > cat-one/pkg-one/pkg-one-2.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="best"
+END
+
+mkdir cat-one/pkg-two
+cat <<"END" > cat-one/pkg-two/pkg-two-1.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="foo"
+END
+
+cat <<"END" > cat-one/pkg-one/pkg-two-2.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="bar"
+END
+
+mkdir cat-one/pkg-three
+cat <<"END" > cat-one/pkg-two/pkg-three-1.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="best one"
+END
+
+cat <<"END" > cat-one/pkg-one/pkg-three-2.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="best one"
+END
+
+mkdir cat-one/pkg-four
+cat <<"END" > cat-one/pkg-two/pkg-four-1.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="best one"
+END
+
+cat <<"END" > cat-one/pkg-one/pkg-four-2.ebuild
+DESCRIPTION="one"
+SLOT="0"
+KEYWORDS="~best ~one"
+END
+
+
diff --git a/src/archtool/help_TEST b/src/archtool/help_TEST
new file mode 100755
index 0000000..d736ff3
--- /dev/null
+++ b/src/archtool/help_TEST
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+./archtool --help
+
diff --git a/src/archtool/keywords_graph.cc b/src/archtool/keywords_graph.cc
new file mode 100644
index 0000000..fddc148
--- /dev/null
+++ b/src/archtool/keywords_graph.cc
@@ -0,0 +1,165 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "keywords_graph.hh"
+#include "command_line.hh"
+
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/compare.hh>
+
+#include <set>
+#include <map>
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+
+using namespace paludis;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+using namespace paludis;
+
+namespace
+{
+ struct CompareByStringLength
+ {
+ template<typename T_>
+ bool
+ operator() (const T_ & l, const T_ & r) const
+ {
+ return stringify(l).length() < stringify(r).length();
+ }
+ };
+
+ void
+ write_keywords_graph(const Environment &, const Repository & repo,
+ const QualifiedPackageName & package)
+ {
+ Context context("When writing keyword graph for '" + stringify(package) + "' in '"
+ + stringify(repo.name()) + "':");
+
+ cout << "Keywords for " << package << ":" << endl;
+ cout << endl;
+
+ VersionSpecCollection::ConstPointer versions(repo.version_specs(package));
+ if (versions->empty())
+ return;
+
+ if (! repo.use_interface)
+ throw InternalError(PALUDIS_HERE, "Repository has no use_interface");
+
+ UseFlagNameCollection::ConstPointer arch_flags(repo.use_interface->arch_flags());
+ if (arch_flags->empty())
+ return;
+
+ unsigned version_specs_columns_width(stringify(*std::max_element(versions->begin(),
+ versions->end(), CompareByStringLength())).length() + 1);
+
+ unsigned tallest_arch_name(stringify(*std::max_element(arch_flags->begin(),
+ arch_flags->end(), CompareByStringLength())).length());
+
+ for (unsigned h = 0 ; h < tallest_arch_name ; ++h)
+ {
+ cout << std::left << std::setw(version_specs_columns_width) << " " << "| ";
+ for (UseFlagNameCollection::Iterator a(arch_flags->begin()), a_end(arch_flags->end()) ;
+ a != a_end ; ++a)
+ {
+ if ((tallest_arch_name - h) > a->data().length())
+ cout << " ";
+ else
+ cout << a->data().at(a->data().length() - tallest_arch_name + h) << " ";
+ }
+ cout << endl;
+ }
+
+ cout << std::string(version_specs_columns_width, '-') << "+"
+ << std::string(arch_flags->size() * 2, '-') << endl;
+ for (VersionSpecCollection::Iterator v(versions->begin()), v_end(versions->end()) ;
+ v != v_end ; ++v)
+ {
+ cout << std::left << std::setw(version_specs_columns_width) << *v << "| ";
+
+ VersionMetadata::ConstPointer metadata(repo.version_metadata(package, *v));
+ if (! metadata->get_ebuild_interface())
+ continue;
+
+ std::set<KeywordName> keywords;
+ WhitespaceTokeniser::get_instance()->tokenise(metadata->get_ebuild_interface()->keywords,
+ create_inserter<KeywordName>(std::inserter(keywords, keywords.end())));
+
+ for (UseFlagNameCollection::Iterator a(arch_flags->begin()), a_end(arch_flags->end()) ;
+ a != a_end ; ++a)
+ {
+ if (keywords.end() != keywords.find(KeywordName(stringify(*a))))
+ cout << "+ ";
+ else if (keywords.end() != keywords.find(KeywordName("~" + stringify(*a))))
+ cout << "~ ";
+ else if (keywords.end() != keywords.find(KeywordName("-" + stringify(*a))))
+ cout << "- ";
+ else if (keywords.end() != keywords.find(KeywordName("-*")))
+ cout << "* ";
+ else
+ cout << " ";
+ }
+
+ cout << endl;
+ }
+
+ cout << endl;
+
+ }
+}
+
+void do_keywords_graph(const Environment & env)
+{
+ Context context("When performing keywords-graph action:");
+
+ for (IndirectIterator<PackageDatabase::RepositoryIterator, const Repository>
+ r(env.package_database()->begin_repositories()),
+ r_end(env.package_database()->end_repositories()) ; r != r_end ; ++r)
+ {
+ CategoryNamePartCollection::ConstPointer cat_names(r->category_names());
+ for (CategoryNamePartCollection::Iterator c(cat_names->begin()), c_end(cat_names->end()) ;
+ c != c_end ; ++c)
+ {
+ if (CommandLine::get_instance()->a_category.specified())
+ if (CommandLine::get_instance()->a_category.args_end() == std::find(
+ CommandLine::get_instance()->a_category.args_begin(),
+ CommandLine::get_instance()->a_category.args_end(),
+ stringify(*c)))
+ continue;
+
+ QualifiedPackageNameCollection::ConstPointer pkg_names(r->package_names(*c));
+ for (QualifiedPackageNameCollection::Iterator p(pkg_names->begin()), p_end(pkg_names->end()) ;
+ p != p_end ; ++p)
+ {
+ if (CommandLine::get_instance()->a_package.specified())
+ if (CommandLine::get_instance()->a_package.args_end() == std::find(
+ CommandLine::get_instance()->a_package.args_begin(),
+ CommandLine::get_instance()->a_package.args_end(),
+ stringify(p->package)))
+ continue;
+
+ write_keywords_graph(env, *r, *p);
+ }
+ }
+ }
+}
+
diff --git a/src/archtool/keywords_graph.hh b/src/archtool/keywords_graph.hh
new file mode 100644
index 0000000..a1ecb20
--- /dev/null
+++ b/src/archtool/keywords_graph.hh
@@ -0,0 +1,27 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_ARCHTOOL_KEYWORDS_GRAPH_HH
+#define PALUDIS_GUARD_SRC_ARCHTOOL_KEYWORDS_GRAPH_HH 1
+
+#include <paludis/environment.hh>
+
+void do_keywords_graph(const paludis::Environment & env);
+
+#endif
diff --git a/src/archtool/man_archtool.cc b/src/archtool/man_archtool.cc
new file mode 100644
index 0000000..a195aaf
--- /dev/null
+++ b/src/archtool/man_archtool.cc
@@ -0,0 +1,36 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command_line.hh"
+#include <paludis/args/man.hh>
+
+#include <iostream>
+#include <cstdlib>
+
+using std::cout;
+using std::endl;
+
+int
+main(int, char *[])
+{
+ paludis::args::generate_man(cout, CommandLine::get_instance());
+ return EXIT_SUCCESS;
+}
+
+
diff --git a/src/archtool/version_TEST b/src/archtool/version_TEST
new file mode 100755
index 0000000..e06d36a
--- /dev/null
+++ b/src/archtool/version_TEST
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./archtool --version