diff options
Diffstat (limited to '0.26.0_alpha1/paludis')
843 files changed, 126540 insertions, 0 deletions
diff --git a/0.26.0_alpha1/paludis/Makefile.am.m4 b/0.26.0_alpha1/paludis/Makefile.am.m4 new file mode 100644 index 000000000..fe1f8808d --- /dev/null +++ b/0.26.0_alpha1/paludis/Makefile.am.m4 @@ -0,0 +1,207 @@ +ifdef(`__gnu__',`',`errprint(`This is not GNU m4... +')m4exit(1)') include(`misc/generated-file.txt') + +dnl vim: set ft=m4 noet : + +define(`filelist', `')dnl +define(`testlist', `')dnl +define(`headerlist', `')dnl +define(`selist', `')dnl +define(`secleanlist', `')dnl +define(`seheaderlist', `')dnl +define(`srlist', `')dnl +define(`srcleanlist', `')dnl +define(`srheaderlist', `')dnl +define(`testscriptlist', `')dnl +define(`addtest', `define(`testlist', testlist `$1_TEST')dnl +$1_TEST_SOURCES = $1_TEST.cc +$1_TEST_LDADD = \ + ihateautomake.o \ + $(top_builddir)/paludis/util/test_extras.o \ + $(top_builddir)/test/libtest.a \ + $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \ + $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.la \ + $(top_builddir)/paludis/repositories/virtuals/libpaludisvirtualsrepository.la \ + libpaludis.la \ + $(top_builddir)/paludis/util/libpaludisutil.la \ + $(DYNAMIC_LD_LIBS) +$1_TEST_CXXFLAGS = -I$(top_srcdir) $(AM_CXXFLAGS) +')dnl +define(`addtestscript', `define(`testscriptlist', testscriptlist `$1_TEST_setup.sh $1_TEST_cleanup.sh')')dnl +define(`addhh', `define(`filelist', filelist `$1.hh')define(`headerlist', headerlist `$1.hh')')dnl +define(`addfwd', `define(`filelist', filelist `$1-fwd.hh')define(`headerlist', headerlist `$1-fwd.hh')')dnl +define(`addhhx', `define(`filelist', filelist `$1.hh')')dnl +define(`addcc', `define(`filelist', filelist `$1.cc')')dnl +define(`addimpl', `define(`filelist', filelist `$1-impl.hh')define(`headerlist', headerlist `$1-impl.hh')')dnl +define(`addsr', `define(`srlist', srlist `$1.sr')dnl +define(`srcleanlist', srcleanlist `$1-sr.hh $1-sr.cc')dnl +define(`srheaderlist', srheaderlist `$1-sr.hh')dnl +$1-sr.hh : $1.sr $(top_srcdir)/misc/make_sr.bash + if ! $(top_srcdir)/misc/make_sr.bash --header $`'(srcdir)/$1.sr > $`'@ ; then rm -f $`'@ ; exit 1 ; fi + +$1-sr.cc : $1.sr $(top_srcdir)/misc/make_sr.bash + if ! $(top_srcdir)/misc/make_sr.bash --source $`'(srcdir)/$1.sr > $`'@ ; then rm -f $`'@ ; exit 1 ; fi + +')dnl +define(`addse', `define(`selist', selist `$1.se')dnl +define(`secleanlist', secleanlist `$1-se.hh $1-se.cc')dnl +define(`seheaderlist', seheaderlist `$1-se.hh')dnl +$1-se.hh : $1.se $(top_srcdir)/misc/make_se.bash + if ! $(top_srcdir)/misc/make_se.bash --header $`'(srcdir)/$1.se > $`'@ ; then rm -f $`'@ ; exit 1 ; fi + +$1-se.cc : $1.se $(top_srcdir)/misc/make_se.bash + if ! $(top_srcdir)/misc/make_se.bash --source $`'(srcdir)/$1.se > $`'@ ; then rm -f $`'@ ; exit 1 ; fi + +')dnl +define(`addthis', `dnl +ifelse(`$2', `hh', `addhh(`$1')', `')dnl +ifelse(`$2', `fwd', `addfwd(`$1')', `')dnl +ifelse(`$2', `hhx', `addhhx(`$1')', `')dnl +ifelse(`$2', `cc', `addcc(`$1')', `')dnl +ifelse(`$2', `sr', `addsr(`$1')', `')dnl +ifelse(`$2', `se', `addse(`$1')', `')dnl +ifelse(`$2', `impl', `addimpl(`$1')', `')dnl +ifelse(`$2', `test', `addtest(`$1')', `')dnl +ifelse(`$2', `testscript', `addtestscript(`$1')', `')')dnl +define(`add', `addthis(`$1',`$2')addthis(`$1',`$3')addthis(`$1',`$4')dnl +addthis(`$1',`$5')addthis(`$1',`$6')addthis(`$1',`$7')addthis(`$1',`$8')')dnl + +AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ + +include(`paludis/files.m4') + +CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda ihateautomake.cc ihateautomake.o +MAINTAINERCLEANFILES = Makefile.in Makefile.am about.hh paludis.hh +DISTCLEANFILES = srcleanlist secleanlist +DEFS= \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DDATADIR=\"$(datadir)\" \ + -DLIBDIR=\"$(libdir)\" \ + -DPYTHONINSTALLDIR=\"$(PYTHON_INSTALL_DIR)\" +EXTRA_DIST = about.hh.in Makefile.am.m4 paludis.hh.m4 files.m4 \ + testscriptlist srlist srcleanlist selist secleanlist \ + repository_blacklist.txt hooker.bash +SUBDIRS = distributions fetchers syncers util selinux . repositories environments args +BUILT_SOURCES = srcleanlist secleanlist + +libpaludis_la_SOURCES = filelist +libpaludis_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 $(PTHREAD_LIBS) + +libpaludispythonhooks_la_SOURCES = python_hooks.cc +libpaludispythonhooks_la_CXXFLAGS = $(AM_CXXFLAGS) \ + @PALUDIS_CXXFLAGS_NO_STRICT_ALIASING@ \ + @PALUDIS_CXXFLAGS_NO_WSHADOW@ \ + -I@PYTHON_INCLUDE_DIR@ +libpaludispythonhooks_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 @BOOST_PYTHON_LIB@ -lpython@PYTHON_VERSION@ +libpaludispythonhooks_la_LIBADD = libpaludis.la + +libpaludismanpagethings_la_SOURCES = name.cc + +libpaludissohooks_TEST_la_SOURCES = sohooks_TEST.cc + +# -rpath to force shared library +libpaludissohooks_TEST_la_LDFLAGS = -rpath /nowhere -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 + +libpaludissohooks_TEST_la_LIBADD = libpaludis.la + +libpaludis_la_LIBADD = \ + $(top_builddir)/paludis/selinux/libpaludisselinux.la \ + $(top_builddir)/paludis/util/libpaludisutil.la \ + @DYNAMIC_LD_LIBS@ \ + $(PTHREAD_LIBS) + +libpaludismanpagethings_la_LIBADD = \ + $(top_builddir)/paludis/util/libpaludisutil.la + +dep_list_TEST_SOURCES += dep_list_TEST.hh +define(`testlist', testlist `dep_list_TEST_blockers')dnl +dep_list_TEST_blockers_SOURCES = dep_list_TEST_blockers.cc dep_list_TEST.hh +dep_list_TEST_blockers_LDADD = \ + ihateautomake.o \ + $(top_builddir)/paludis/util/test_extras.o \ + $(top_builddir)/test/libtest.a \ + $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \ + $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.la \ + $(top_builddir)/paludis/repositories/virtuals/libpaludisvirtualsrepository.la \ + libpaludis.la \ + $(top_builddir)/paludis/util/libpaludisutil.la \ + $(DYNAMIC_LD_LIBS) +dep_list_TEST_blockers_CXXFLAGS = -I$(top_srcdir) $(AM_CXXFLAGS) + +TESTS = testlist + +check_PROGRAMS = $(TESTS) +check_SCRIPTS = testscriptlist +check_LTLIBRARIES = libpaludissohooks_TEST.la + +paludis_datadir = $(datadir)/paludis +paludis_data_DATA = repository_blacklist.txt + +paludis_libexecdir = $(libexecdir)/paludis +paludis_libexec_SCRIPTS = hooker.bash + +if MONOLITHIC + +noinst_LTLIBRARIES = libpaludis.la libpaludismanpagethings.la + +else + +lib_LTLIBRARIES = libpaludis.la +noinst_LTLIBRARIES = libpaludismanpagethings.la + +if ENABLE_PYTHON_HOOKS +lib_LTLIBRARIES += libpaludispythonhooks.la +endif + +endif + + +paludis_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/ +paludis_include_HEADERS = headerlist srheaderlist seheaderlist + +Makefile.am : Makefile.am.m4 files.m4 + $(top_srcdir)/misc/do_m4.bash Makefile.am + +paludis.hh : paludis.hh.m4 files.m4 + $(top_srcdir)/misc/do_m4.bash paludis.hh + +comparison_policy.hh : comparison_policy.hh.m4 + $(top_srcdir)/misc/do_m4.bash comparison_policy.hh.m4 + +ihateautomake.cc : all + test -f $@ || touch $@ + +changequote(`<', `>') +built-sources : $(BUILT_SOURCES) + for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done + +DISTCHECK_DEPS = libpaludis.la libpaludismanpagethings.la + +distcheck-deps-local : $(DISTCHECK_DEPS) + +distcheck-deps : distcheck-deps-subdirs + +distcheck-deps-subdirs : + for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \ + else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done + +TESTS_ENVIRONMENT = env \ + PALUDIS_EBUILD_DIR="$(top_srcdir)/paludis/repositories/e/ebuild/" \ + PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/repositories/e/eapis/" \ + PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \ + PALUDIS_DISTRIBUTION="gentoo" \ + PALUDIS_HOOKER_DIR="$(top_srcdir)/paludis/" \ + PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \ + PALUDIS_SKIP_CONFIG="yes" \ + PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \ + TEST_SCRIPT_DIR="$(srcdir)/" \ + SO_SUFFIX=@VERSION_LIB_CURRENT@ \ + PYTHONPATH="$(top_builddir)/python/" \ + PALUDIS_PYTHON_DIR="$(top_srcdir)/python/" \ + LD_LIBRARY_PATH="`echo $$LD_LIBRARY_PATH: | sed -e 's,^:,,'`` \ + $(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/.libs/ \ + `:`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/.libs/ \ + `:`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/python/.libs/`" \ + bash $(top_srcdir)/test/run_test.sh + diff --git a/0.26.0_alpha1/paludis/about.hh.in b/0.26.0_alpha1/paludis/about.hh.in new file mode 100644 index 000000000..8827abde0 --- /dev/null +++ b/0.26.0_alpha1/paludis/about.hh.in @@ -0,0 +1,128 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 + */ + +@GENERATED_FILE@ + +#ifndef PALUDIS_GUARD_PALUDIS_ABOUT_HH +#define PALUDIS_GUARD_PALUDIS_ABOUT_HH 1 + +/** \file + * Defines constants giving the Paludis version number and information about + * how Paludis was built. + * + * \section Examples + * + * - \ref example_about.cc "example_about.cc" + * + * \ingroup g_about + */ + +/** + * The package name (eg Paludis). + * + * \ingroup g_about + */ +#define PALUDIS_PACKAGE "@PACKAGE@" + +/** + * The major version (eg 0.4.1 -> 0). + * + * \ingroup g_about + */ +#define PALUDIS_VERSION_MAJOR @VERSION_MAJOR@ + +/** + * The minor version (eg 0.4.1 -> 4). + * + * \ingroup g_about + */ +#define PALUDIS_VERSION_MINOR @VERSION_MINOR@ + +/** + * The micro version (eg 0.4.1 -> 1). + * + * \ingroup g_about + */ +#define PALUDIS_VERSION_MICRO @VERSION_MICRO@ + +/** + * The version suffix (eg "_alpha1"), often an empty string. + * + * \ingroup g_about + */ +#define PALUDIS_VERSION_SUFFIX "@VERSION_SUFFIX@" + +/** + * The version, two digits per part (eg 1.3.5 -> 10305). + * + * \ingroup g_about + */ +#define PALUDIS_VERSION ((100 * 100 * PALUDIS_VERSION_MAJOR) \ + + (100 * PALUDIS_VERSION_MINOR) + PALUDIS_VERSION_MICRO) + +/** + * The subversion revision, if applicable (eg "65" or "65M" or ""). + * + * \ingroup g_about + */ +#define PALUDIS_SUBVERSION_REVISION "@SVNVERSION@" + +/** + * The CXXFLAGS used to build Paludis. + * + * \ingroup g_about + */ +#define PALUDIS_BUILD_CXXFLAGS "@CXXFLAGS@" + +/** + * The LDFLAGS used to build Paludis. + * + * \ingroup g_about + */ +#define PALUDIS_BUILD_LDFLAGS "@LDFLAGS@" + +/** + * The compiler used to build Paludis. + * + * \ingroup g_about + */ +#define PALUDIS_BUILD_CXX "@CXX@" + +/** + * The user who built Paludis. + * + * \ingroup g_about + */ +#define PALUDIS_BUILD_USER "@BUILDUSER@" + +/** + * The host on which Paludis was built. + * + * \ingroup g_about + */ +#define PALUDIS_BUILD_HOST "@BUILDHOST@" + +/** + * The date when Paludis was built. + * + * \ingroup g_about + */ +#define PALUDIS_BUILD_DATE "@BUILDDATE@" + +#endif diff --git a/0.26.0_alpha1/paludis/about_TEST.cc b/0.26.0_alpha1/paludis/about_TEST.cc new file mode 100644 index 000000000..61ec0aefa --- /dev/null +++ b/0.26.0_alpha1/paludis/about_TEST.cc @@ -0,0 +1,83 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 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 <paludis/about.hh> +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace test; +using namespace paludis; + +/** + * \file + * Test cases for about.hh . + * + */ + +namespace test_cases +{ + /** + * \test Version tests. + * + */ + struct VersionTest : TestCase + { + VersionTest() : TestCase("about test") { } + + void run() + { + TEST_CHECK(PALUDIS_VERSION_MAJOR >= 0); + TEST_CHECK(PALUDIS_VERSION_MAJOR <= 9); + + TEST_CHECK(PALUDIS_VERSION_MINOR >= 0); + TEST_CHECK(PALUDIS_VERSION_MINOR <= 99); + + TEST_CHECK(PALUDIS_VERSION_MICRO >= 0); + TEST_CHECK(PALUDIS_VERSION_MICRO <= 99); + + TEST_CHECK(PALUDIS_VERSION >= 0); + TEST_CHECK(PALUDIS_VERSION <= 99999); + TEST_CHECK_EQUAL(PALUDIS_VERSION, 10000 * PALUDIS_VERSION_MAJOR + + 100 * PALUDIS_VERSION_MINOR + PALUDIS_VERSION_MICRO); + + TEST_CHECK(std::string(PALUDIS_SUBVERSION_REVISION) != "i am a fish"); + } + } test_case_about; + + /** + * \test Build info tests. + * + */ + struct BuildInfoTest : TestCase + { + BuildInfoTest() : TestCase("build info test") { } + + void run() + { + TEST_CHECK(! std::string(PALUDIS_BUILD_CXX).empty()); + TEST_CHECK(! std::string(PALUDIS_BUILD_CXXFLAGS).empty()); + TEST_CHECK(std::string(PALUDIS_BUILD_LDFLAGS) != "i am a fish"); + + TEST_CHECK(! std::string(PALUDIS_BUILD_USER).empty()); + TEST_CHECK(! std::string(PALUDIS_BUILD_HOST).empty()); + TEST_CHECK(! std::string(PALUDIS_BUILD_DATE).empty()); + } + } test_case_build_info; +} + diff --git a/0.26.0_alpha1/paludis/action-fwd.hh b/0.26.0_alpha1/paludis/action-fwd.hh new file mode 100644 index 000000000..ceb1b3c38 --- /dev/null +++ b/0.26.0_alpha1/paludis/action-fwd.hh @@ -0,0 +1,67 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_ACTION_FWD_HH +#define PALUDIS_GUARD_PALUDIS_ACTION_FWD_HH 1 + +#include <iosfwd> +#include <paludis/util/attributes.hh> + +/** \file + * Forward declarations for paludis/action.hh . + * + * \ingroup g_actions + */ + +namespace paludis +{ + class Action; + class InstallAction; + class InstalledAction; + class UninstallAction; + class PretendAction; + class ConfigAction; + class FetchAction; + class InfoAction; + + class SupportsActionTestBase; + template <typename A_> class SupportsActionTest; + + class ActionVisitorTypes; + class SupportsActionTestVisitorTypes; + + class ActionError; + class UnsupportedActionError; + class InstallActionError; + class FetchActionError; + class UninstallActionError; + class ConfigActionError; + class InfoActionError; + + class FetchActionFailure; + + class InstallActionOptions; + class UninstallActionOptions; + class FetchActionOptions; + +#include <paludis/action-se.hh> + +} + +#endif diff --git a/0.26.0_alpha1/paludis/action.cc b/0.26.0_alpha1/paludis/action.cc new file mode 100644 index 000000000..bf8b6141f --- /dev/null +++ b/0.26.0_alpha1/paludis/action.cc @@ -0,0 +1,272 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 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 <paludis/action.hh> +#include <paludis/util/visitor-impl.hh> +#include <paludis/util/exception.hh> +#include <paludis/util/stringify.hh> +#include <paludis/util/sequence-impl.hh> + +using namespace paludis; + +#include <paludis/action-se.cc> +#include <paludis/action-sr.cc> + +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, InstallAction>; +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, ConfigAction>; +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, InfoAction>; +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, PretendAction>; +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, InstalledAction>; +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, UninstallAction>; +template class AcceptInterfaceVisitsThis<ActionVisitorTypes, FetchAction>; + +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<InstallAction> >; +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<ConfigAction> >; +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<InfoAction> >; +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<PretendAction> >; +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<InstalledAction> >; +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<UninstallAction> >; +template class AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<FetchAction> >; + +template class Sequence<FetchActionFailure>; + +Action::~Action() +{ +} + +namespace paludis +{ + template <> + struct Implementation<InstallAction> + { + const InstallActionOptions options; + + Implementation(const InstallActionOptions & o) : + options(o) + { + } + }; +} + +InstallAction::InstallAction(const InstallActionOptions & o) : + PrivateImplementationPattern<InstallAction>(new Implementation<InstallAction>(o)), + options(_imp->options) +{ +} + +InstallAction::~InstallAction() +{ +} + +namespace paludis +{ + template <> + struct Implementation<FetchAction> + { + const FetchActionOptions options; + + Implementation(const FetchActionOptions & o) : + options(o) + { + } + }; +} + +FetchAction::FetchAction(const FetchActionOptions & o) : + PrivateImplementationPattern<FetchAction>(new Implementation<FetchAction>(o)), + options(_imp->options) +{ +} + +FetchAction::~FetchAction() +{ +} + +namespace paludis +{ + template <> + struct Implementation<UninstallAction> + { + const UninstallActionOptions options; + + Implementation(const UninstallActionOptions & o) : + options(o) + { + } + }; +} + +UninstallAction::UninstallAction(const UninstallActionOptions & o) : + PrivateImplementationPattern<UninstallAction>(new Implementation<UninstallAction>(o)), + options(_imp->options) +{ +} + +UninstallAction::~UninstallAction() +{ +} + +namespace paludis +{ + template <> + struct Implementation<PretendAction> + { + bool failed; + + Implementation() : + failed(false) + { + } + }; +} + +PretendAction::PretendAction() : + PrivateImplementationPattern<PretendAction>(new Implementation<PretendAction>) +{ +} + +PretendAction::~PretendAction() +{ +} + +bool +PretendAction::failed() const +{ + return _imp->failed; +} + +void +PretendAction::set_failed() +{ + _imp->failed = true; +} + +SupportsActionTestBase::~SupportsActionTestBase() +{ +} + +UnsupportedActionError::UnsupportedActionError(const PackageID & id, const Action & a) throw () : + ActionError("Unsupported action '" + stringify(a) + "' on '" + stringify(id) + "'") +{ +} + +namespace +{ + struct ActionStringifier : + ConstVisitor<ActionVisitorTypes> + { + std::ostream & s; + + ActionStringifier(std::ostream & ss) : + s(ss) + { + } + + void visit(const InstallAction & a) + { + s << "install to "; + if (a.options.destination) + s << &a.options.destination; + else + s << "nowhere"; + } + + void visit(const UninstallAction &) + { + s << "uninstall"; + } + + void visit(const PretendAction &) + { + s << "pretend"; + } + + void visit(const InstalledAction &) + { + s << "installed"; + } + + void visit(const ConfigAction &) + { + s << "config"; + } + + void visit(const InfoAction &) + { + s << "info"; + } + + void visit(const FetchAction &) + { + s << "fetch"; + } + }; +} + +std::ostream & +paludis::operator<< (std::ostream & s, const Action & a) +{ + ActionStringifier t(s); + a.accept(t); + return s; +} + +ActionError::ActionError(const std::string & msg) throw () : + Exception(msg) +{ +} + +InstallActionError::InstallActionError(const std::string & msg) throw () : + ActionError("Install error: " + msg) +{ +} + +FetchActionError::FetchActionError(const std::string & msg, + const tr1::shared_ptr<const Sequence<FetchActionFailure> > & e) throw () : + ActionError("Fetch error: " + msg), + _failures(e) +{ +} + +FetchActionError::FetchActionError(const std::string & msg) throw () : + ActionError("Fetch error: " + msg) +{ +} + +const tr1::shared_ptr<const Sequence<FetchActionFailure> > +FetchActionError::failures() const +{ + return _failures; +} + +UninstallActionError::UninstallActionError(const std::string & msg) throw () : + ActionError("Uninstall error: " + msg) +{ +} + +ConfigActionError::ConfigActionError(const std::string & msg) throw () : + ActionError("Configuration error: " + msg) +{ +} + +InfoActionError::InfoActionError(const std::string & msg) throw () : + ActionError("Info error: " + msg) +{ +} + diff --git a/0.26.0_alpha1/paludis/action.hh b/0.26.0_alpha1/paludis/action.hh new file mode 100644 index 000000000..995b02d70 --- /dev/null +++ b/0.26.0_alpha1/paludis/action.hh @@ -0,0 +1,459 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_ACTION_HH +#define PALUDIS_GUARD_PALUDIS_ACTION_HH 1 + +#include <paludis/action-fwd.hh> +#include <paludis/repository-fwd.hh> +#include <paludis/package_id-fwd.hh> +#include <paludis/util/attributes.hh> +#include <paludis/util/visitor.hh> +#include <paludis/util/exception.hh> +#include <paludis/util/sr.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <paludis/util/sequence-fwd.hh> + +/** \file + * Declarations for action-related classes. + * + * \ingroup g_actions + * + * \section Examples + * + * - \ref example_action.cc "example_action.cc" + */ + +namespace paludis +{ + +#include <paludis/action-sr.hh> + + /** + * Types for visiting an action. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + struct ActionVisitorTypes : + VisitorTypes< + ActionVisitorTypes, + Action, + InstallAction, + FetchAction, + InstalledAction, + UninstallAction, + PretendAction, + ConfigAction, + InfoAction + > + { + }; + + /** + * Types for visiting a supports action query. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + struct SupportsActionTestVisitorTypes : + VisitorTypes< + SupportsActionTestVisitorTypes, + SupportsActionTestBase, + SupportsActionTest<InstallAction>, + SupportsActionTest<FetchAction>, + SupportsActionTest<InstalledAction>, + SupportsActionTest<UninstallAction>, + SupportsActionTest<PretendAction>, + SupportsActionTest<ConfigAction>, + SupportsActionTest<InfoAction> + > + { + }; + + /** + * An Action represents an action that can be executed by a PackageID via + * PackageID::perform_action. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE Action : + public virtual AcceptInterface<ActionVisitorTypes> + { + public: + ///\name Basic operations + ///\{ + + virtual ~Action() = 0; + + ///\} + }; + + /** + * An InstallAction is used by InstallTask to perform a build / install on a + * PackageID. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE InstallAction : + public Action, + private PrivateImplementationPattern<InstallAction>, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, InstallAction> + { + public: + ///\name Basic operations + ///\{ + + InstallAction(const InstallActionOptions &); + ~InstallAction(); + + ///\} + + /// Options for the action. + const InstallActionOptions & options; + }; + + /** + * A FetchAction can be used to fetch source files for a PackageID using + * PackageID::perform_action. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE FetchAction : + public Action, + private PrivateImplementationPattern<FetchAction>, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, FetchAction> + { + public: + ///\name Basic operations + ///\{ + + FetchAction(const FetchActionOptions &); + ~FetchAction(); + + ///\} + + /// Options for the action. + const FetchActionOptions & options; + }; + + /** + * An UninstallAction is used by UninstallTask to uninstall a PackageID. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE UninstallAction : + public Action, + private PrivateImplementationPattern<UninstallAction>, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, UninstallAction> + { + public: + ///\name Basic operations + ///\{ + + UninstallAction(const UninstallActionOptions &); + ~UninstallAction(); + + ///\} + + /// Options for the action. + const UninstallActionOptions & options; + }; + + /** + * InstalledAction is a dummy action used by SupportsActionTest and + * query::SupportsAction to determine whether a PackageID is installed. + * + * Performing an InstalledAction does not make sense and will do nothing. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE InstalledAction : + public Action, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, InstalledAction> + { + }; + + /** + * A PretendAction is used by InstallTask to handle install-pretend-phase + * checks on a PackageID. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE PretendAction : + public Action, + private PrivateImplementationPattern<PretendAction>, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, PretendAction> + { + public: + ///\name Basic operations + ///\{ + + PretendAction(); + ~PretendAction(); + + ///\} + + /// Did our pretend phase fail? + bool failed() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + /// Mark the action as failed. + void set_failed(); + }; + + /** + * A ConfigAction is used via PackageID::perform_action to execute + * post-install configuration (for example, via 'paludis --config') + * on a PackageID. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE ConfigAction : + public Action, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, ConfigAction> + { + }; + + /** + * An InfoAction is used via PackageID::perform_action to execute + * additional information (for example, via 'paludis --info') + * on a PackageID. + * + * This action potentially makes sense for both installed and + * installable packages. Unlike Ebuild EAPI-0 'pkg_info', this + * action is not specifically tied to installed packages. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE InfoAction: + public Action, + public AcceptInterfaceVisitsThis<ActionVisitorTypes, InfoAction> + { + }; + + /** + * Base class for SupportsActionTest<>. + * + * \see SupportsActionTest<> + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + class PALUDIS_VISIBLE SupportsActionTestBase : + public virtual AcceptInterface<SupportsActionTestVisitorTypes> + { + public: + virtual ~SupportsActionTestBase() = 0; + }; + + /** + * Instantiated with an Action subclass as its template parameter, + * SupportsActionTest<> is used by PackageID::supports_action and + * Repository::some_ids_might_support_action to query whether a + * particular action is supported by that PackageID or potentially + * supported by some IDs in that Repository. + * + * Use of a separate class, rather than a mere Action, avoids the + * need to create bogus options for the more complicated Action + * subclasses. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + template <typename A_> + class PALUDIS_VISIBLE SupportsActionTest : + public SupportsActionTestBase, + public AcceptInterfaceVisitsThis<SupportsActionTestVisitorTypes, SupportsActionTest<A_> > + { + }; + + /** + * An Action can be written to a std::ostream. + * + * \since 0.26 + * \ingroup g_actions + * \nosubgrouping + */ + std::ostream & operator<< (std::ostream &, const Action &) PALUDIS_VISIBLE; + + /** + * Parent class for Action related errors. + * + * \ingroup g_actions + * \ingroup g_exceptions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE ActionError : + public Exception + { + public: + ///\name Basic operations + ///\{ + + ActionError(const std::string & msg) throw (); + + ///\} + }; + + /** + * Thrown if a PackageID is asked to perform an Action that it does + * not support. + * + * \ingroup g_exceptions + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE UnsupportedActionError : + public ActionError + { + public: + ///\name Basic operations + ///\{ + + UnsupportedActionError(const PackageID &, const Action &) throw (); + + ///\} + }; + + /** + * Thrown if a PackageID fails to perform an InstallAction. + * + * \ingroup g_exceptions + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE InstallActionError : public ActionError + { + public: + ///\name Basic operations + ///\{ + + InstallActionError(const std::string & msg) throw (); + + ///\} + }; + + /** + * Thrown if a PackageID fails to perform a FetchAction. + * + * \ingroup g_exceptions + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE FetchActionError : + public ActionError + { + private: + const tr1::shared_ptr<const Sequence<FetchActionFailure> > _failures; + + public: + ///\name Basic operations + ///\{ + + FetchActionError(const std::string &) throw (); + FetchActionError(const std::string &, const tr1::shared_ptr<const Sequence<FetchActionFailure> > &) throw (); + + ///\} + + /// More information about failed fetches. + const tr1::shared_ptr<const Sequence<FetchActionFailure> > failures() const PALUDIS_ATTRIBUTE((warn_unused_result)); + }; + + /** + * Thrown if a PackageID fails to perform an UninstallAction. + * + * \ingroup g_exceptions + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE UninstallActionError : public ActionError + { + public: + ///\name Basic operations + ///\{ + + UninstallActionError(const std::string & msg) throw (); + + ///\} + }; + + /** + * Thrown if a PackageID fails to perform a ConfigAction. + * + * \ingroup g_exceptions + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE ConfigActionError : public ActionError + { + public: + ///\name Basic operations + ///\{ + + ConfigActionError(const std::string & msg) throw (); + + ///\} + }; + + /** + * Thrown if a PackageID fails to perform an InfoAction. + * + * \ingroup g_exceptions + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE InfoActionError : public ActionError + { + public: + ///\name Basic operations + ///\{ + + InfoActionError(const std::string & msg) throw (); + + ///\} + }; +} + +#endif diff --git a/0.26.0_alpha1/paludis/action.se b/0.26.0_alpha1/paludis/action.se new file mode 100644 index 000000000..35be7b137 --- /dev/null +++ b/0.26.0_alpha1/paludis/action.se @@ -0,0 +1,45 @@ +#!/bin/bash +# vim: set sw=4 sts=4 et ft=sh : + +make_enum_InstallActionDebugOption() +{ + prefix iado + + key iado_none "No debugging" + key iado_split "Split debugging" + key iado_internal "Internal debugging" + + doxygen_comment << "END" + /** + * Debug build mode for an InstallAction. + * + * May be ignored by some repositories, and by packages where there + * isn't a sensible concept of debugging. + * + * \see InstallAction + * \ingroup g_actions + * \since 0.26 + */ +END +} + +make_enum_InstallActionChecksOption() +{ + prefix iaco + + key iaco_none "No checks" + key iaco_default "Checks where they would usually be carried out" + key iaco_always "Always use checks" + + doxygen_comment << "END" + /** + * Whether to run post-build checks (for example, 'make check' or 'src_test'), + * if they are available. + * + * \see InstallAction + * \ingroup g_actions + * \since 0.26 + */ +END +} + diff --git a/0.26.0_alpha1/paludis/action.sr b/0.26.0_alpha1/paludis/action.sr new file mode 100644 index 000000000..435237353 --- /dev/null +++ b/0.26.0_alpha1/paludis/action.sr @@ -0,0 +1,88 @@ +#!/bin/bash +# vim: set sw=4 sts=4 et : + +make_class_FetchActionOptions() +{ + visible + allow_named_args + + key fetch_unneeded bool + key safe_resume bool + + doxygen_comment << "END" + /** + * Options for FetchAction. + * + * \see FetchAction + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ +END +} + + +make_class_InstallActionOptions() +{ + visible + allow_named_args + + key no_config_protect bool + key debug_build InstallActionDebugOption + key checks InstallActionChecksOption + key destination "tr1::shared_ptr<Repository>" + + doxygen_comment << "END" + /** + * Options for InstallAction. + * + * \see InstallAction + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ +END +} + +make_class_UninstallActionOptions() +{ + visible + allow_named_args + + key no_config_protect bool + + doxygen_comment << "END" + /** + * Options for UninstallAction. + * + * \see UninstallAction + * \ingroup g_actions + * \since 0.26 + * \nosubgrouping + */ +END +} + +make_class_FetchActionFailure() +{ + visible + allow_named_args + + key target_file std::string + key requires_manual_fetching bool + key failed_automatic_fetching bool + key failed_integrity_checks std::string + + doxygen_comment << "END" + /** + * A failed fetch action part. + * + * \see FetchActionError + * \ingroup g_actions + * \ingroup g_exceptions + * \ingroup g_actions + * \nosubgrouping + */ +END +} + diff --git a/0.26.0_alpha1/paludis/args/Makefile.am b/0.26.0_alpha1/paludis/args/Makefile.am new file mode 100644 index 000000000..b0b4df7c8 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/Makefile.am @@ -0,0 +1,84 @@ +CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda +MAINTAINERCLEANFILES = Makefile.in +AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ + +TESTS = \ + args_TEST + +paludis_args_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/args/ + +paludis_args_include_HEADERS = \ + args.hh \ + args_error.hh \ + args_group.hh \ + args_handler.hh \ + args_option.hh \ + bad_argument.hh \ + args_visitor.hh \ + args_dumper.hh \ + man.hh \ + checks_arg.hh \ + debug_build_arg.hh \ + deps_option_arg.hh \ + log_level_arg.hh \ + dep_list_args_group.hh \ + install_args_group.hh \ + do_help.hh + +libpaludisargs_la_SOURCES = \ + args.cc \ + args_error.cc \ + args_group.cc \ + args_handler.cc \ + args_option.cc \ + bad_argument.cc \ + args_visitor.cc \ + args_dumper.cc \ + checks_arg.cc \ + debug_build_arg.cc \ + deps_option_arg.cc \ + log_level_arg.cc \ + dep_list_args_group.cc \ + install_args_group.cc + +libpaludisman_a_SOURCES = \ + man.cc + +libpaludisargs_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 + +libpaludisargs_la_LIBADD = \ + $(top_builddir)/paludis/libpaludis.la + $(top_builddir)/paludis/util/libpaludisutil.la + +TESTS_ENVIRONMENT = env PALUDIS_OPTIONS="" \ + TEST_SCRIPT_DIR="$(srcdir)/" \ + PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \ + PALUDIS_DISTRIBUTION="gentoo" \ + bash $(top_srcdir)/test/run_test.sh + +lib_LTLIBRARIES = libpaludisargs.la +noinst_LIBRARIES = libpaludisman.a + +check_PROGRAMS = $(TESTS) + +test_ldadd = \ + libpaludisargs.la \ + $(top_builddir)/test/libtest.a \ + $(top_builddir)/paludis/util/libpaludisutil.la + +args_TEST_SOURCES = args_TEST.cc +args_TEST_LDADD = $(test_ldadd) + +built-sources : $(BUILT_SOURCES) + for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done + +DISTCHECK_DEPS = libpaludisargs.la libpaludisman.a + +distcheck-deps-local : $(DISTCHECK_DEPS) + +distcheck-deps : distcheck-deps-subdirs + +distcheck-deps-subdirs : + for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \ + else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done + diff --git a/0.26.0_alpha1/paludis/args/args.cc b/0.26.0_alpha1/paludis/args/args.cc new file mode 100644 index 000000000..cb7f5e1da --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "args.hh" + diff --git a/0.26.0_alpha1/paludis/args/args.hh b/0.26.0_alpha1/paludis/args/args.hh new file mode 100644 index 000000000..877de08db --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args.hh @@ -0,0 +1,39 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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_ARGS_ARGS_HH +#define PALUDIS_GUARD_ARGS_ARGS_HH 1 + +/** \file + * Master include file for command line argument handling. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +#include <paludis/args/args_error.hh> +#include <paludis/args/args_group.hh> +#include <paludis/args/args_handler.hh> +#include <paludis/args/args_option.hh> +#include <paludis/args/bad_argument.hh> + +#endif diff --git a/0.26.0_alpha1/paludis/args/args_TEST.cc b/0.26.0_alpha1/paludis/args/args_TEST.cc new file mode 100644 index 000000000..9a29fd6f3 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_TEST.cc @@ -0,0 +1,237 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 <paludis/args/args.hh> +#include <paludis/args/args_error.hh> +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <algorithm> + +using namespace paludis; +using namespace paludis::args; +using namespace test; + +/** \file + * Test cases for paludis::args things. + * + */ + +#ifndef DOXYGEN + +struct CommandLine : public ArgsHandler +{ + ArgsGroup group_one; + SwitchArg arg_foo; + SwitchArg arg_bar; + SwitchArg arg_dummy; + SwitchArg arg_removed; + + ArgsGroup group_two; + SwitchArg arg_baz; + AliasArg arg_other_baz; + StringArg arg_something; + StringArg arg_monkey; + AliasArg arg_other_monkey; + IntegerArg arg_somenum; + EnumArg arg_enum; + + ArgsGroup group_three; + EnumArg arg_other_enum; + StringSetArg arg_stringset; + + CommandLine(); + ~CommandLine(); + + std::string app_name() const + { + return "args_TEST"; + } + + std::string app_synopsis() const + { + return "tests for args"; + } + + std::string app_description() const + { + return "Tests args"; + } +}; + +CommandLine::CommandLine() : + group_one(this, "Group one", "Description of group one"), + arg_foo(&group_one, "foo", 'f', "Enable foo"), + arg_bar(&group_one, "bar", 'b', "Enable bar"), + arg_dummy(&group_one, "dummy", 'd', "Enable something else"), + arg_removed(&group_one, "removed", 'r', "Removed"), + + group_two(this, "Group two", "Description of group two"), + arg_baz(&group_two, "baz", 'z', "Enable baz"), + arg_other_baz(&arg_baz, "other-baz"), + arg_something(&group_two, "something", 's', "Value of something"), + arg_monkey(&group_two, "monkey", 'm', "A monkey?"), + arg_other_monkey(&arg_monkey, "other-monkey"), + arg_somenum(&group_two, "num", 'n', "Some number"), + arg_enum(&group_two, "enum", 'e', "One of three", EnumArg::EnumArgOptions("one", "Option one")("two", "option two")("three", "option three"), "two"), + + group_three(this, "Group three", "Description of group three"), + arg_other_enum(&group_three, "something", '\0', "Blah.", EnumArg::EnumArgOptions("a", "A")("b", "B")("c", "C"), "b"), + arg_stringset(&group_three, "stringset", 't', "A StringSet.") +{ +} + +CommandLine::~CommandLine() +{ +} + +#endif + +namespace test_cases +{ + /** + * \test Simple args tests. + * + */ + struct ArgsTestSimple : TestCase + { + ArgsTestSimple() : TestCase("simple") { } + + void run() + { + const char * args[] = { "program-name", "--other-monkey", "chimp", "--other-baz", + "-fsne", "blah", "7", "three", "--", "--dummy", "one", "two" }; + CommandLine c1; + c1.run(12, args, "", "", ""); + TEST_CHECK(c1.arg_foo.specified()); + TEST_CHECK(! c1.arg_bar.specified()); + TEST_CHECK(c1.arg_baz.specified()); + TEST_CHECK(c1.arg_other_baz.specified()); + TEST_CHECK(c1.arg_something.specified()); + TEST_CHECK(c1.arg_something.argument() == "blah"); + TEST_CHECK(c1.arg_somenum.specified()); + TEST_CHECK(c1.arg_somenum.argument() == 7); + TEST_CHECK(c1.arg_enum.specified()); + TEST_CHECK(c1.arg_enum.argument() == "three"); + TEST_CHECK(! c1.arg_dummy.specified()); + TEST_CHECK(! c1.arg_other_enum.specified()); + TEST_CHECK(c1.arg_other_enum.argument() == "b"); + TEST_CHECK(c1.arg_monkey.specified()); + TEST_CHECK(c1.arg_monkey.argument() == "chimp"); + + TEST_CHECK_EQUAL(std::distance(c1.begin_parameters(), c1.end_parameters()), 3); + TEST_CHECK_EQUAL(*c1.begin_parameters(), "--dummy"); + TEST_CHECK_EQUAL(*++c1.begin_parameters(), "one"); + TEST_CHECK_EQUAL(*++(++(c1.begin_parameters())), "two"); + } + } test_args_simple; + + /** + * \test Missing parameters tests. + * + */ + struct ArgsTestNoParam : TestCase + { + ArgsTestNoParam() : TestCase("Missing parameters") { } + + void run() + { + const char *args[] = { "program-name", "-e" }; + CommandLine c1; + TEST_CHECK_THROWS(c1.run(2, args, "", "", ""), MissingValue); + } + } test_args_no_param; + + /** + * \test Removed arguments tests. + * + */ + struct ArgsTestRemovedArg : TestCase + { + ArgsTestRemovedArg() : TestCase("Removed arguments") { } + + void run() + { + const char *args1[] = { "program-name", "--removed" }; + const char *args2[] = { "program-name", "-r" }; + CommandLine c1; + c1.run(2, args1, "", "", ""); + TEST_CHECK(true); + c1.run(2, args2, "", "", ""); + TEST_CHECK(true); + c1.arg_removed.remove(); + TEST_CHECK_THROWS(c1.run(2, args1, "", "", ""), BadArgument); + TEST_CHECK_THROWS(c1.run(2, args2, "", "", ""), BadArgument); + } + } test_args_removed_arg; + + /** + * \test Default arguments tests. + * + */ + struct ArgsTestDefaultArg : TestCase + { + ArgsTestDefaultArg() : TestCase("Default arguments") { } + + void run() + { + const char *args1[] = { "program-name", "--enum", "three" }; + const char *args2[] = { "program-name" }; + CommandLine c1, c2, c3, c4; + c2.arg_enum.set_default_arg("one"); + c4.arg_enum.set_default_arg("one"); + + c1.run(3, args1, "", "", ""); + c2.run(3, args1, "", "", ""); + c1.run(1, args2, "", "", ""); + c2.run(1, args2, "", "", ""); + + TEST_CHECK(c1.arg_enum.specified()); + TEST_CHECK(c2.arg_enum.specified()); + TEST_CHECK(! c3.arg_enum.specified()); + TEST_CHECK(! c4.arg_enum.specified()); + + TEST_CHECK_EQUAL(c1.arg_enum.argument(), "three"); + TEST_CHECK_EQUAL(c2.arg_enum.argument(), "three"); + TEST_CHECK_EQUAL(c3.arg_enum.argument(), "two"); + TEST_CHECK_EQUAL(c4.arg_enum.argument(), "one"); + } + } test_args_default_arg; + + /** + * \test String tests. + * + */ + struct ArgsTestStringSet : TestCase + { + ArgsTestStringSet() : TestCase("StringSet") { } + + void run() + { + const char *args[] = { "program-name", "--stringset", "one", "-t", "two", "-t", "three", "fnord" }; + CommandLine c1; + c1.run(8, args, "", "", ""); + TEST_CHECK(c1.arg_stringset.specified()); + TEST_CHECK(std::find(c1.arg_stringset.begin_args(), c1.arg_stringset.end_args(), "one") != c1.arg_stringset.end_args()); + TEST_CHECK(std::find(c1.arg_stringset.begin_args(), c1.arg_stringset.end_args(), "two") != c1.arg_stringset.end_args()); + TEST_CHECK(std::find(c1.arg_stringset.begin_args(), c1.arg_stringset.end_args(), "three") != c1.arg_stringset.end_args()); + TEST_CHECK(std::find(c1.arg_stringset.begin_args(), c1.arg_stringset.end_args(), "fnord") == c1.arg_stringset.end_args()); + } + } test_args_string_set; +} + diff --git a/0.26.0_alpha1/paludis/args/args_dumper.cc b/0.26.0_alpha1/paludis/args/args_dumper.cc new file mode 100644 index 000000000..5eacfc477 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_dumper.cc @@ -0,0 +1,108 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Stephen Bennett <spb@gentoo.org> + * + * 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 <paludis/args/args_dumper.hh> +#include <paludis/args/args_option.hh> +#include <paludis/util/visitor-impl.hh> + +#include <sstream> + +using namespace paludis; +using namespace paludis::args; + +ArgsDumper::ArgsDumper(std::ostream & os) : + _os(os) +{ +} + +void ArgsDumper::generic_visit(const ArgsOption & a) +{ + std::stringstream p; + p << " --" << a.long_name(); + if (a.short_name()) + p << ", -" << a.short_name(); + if (p.str().length() < 24) + p << std::string(24 - p.str().length(), ' '); + else + p << std::endl << std::string(24, ' '); + _os << p.str(); + _os << " " << a.description() << std::endl; +} + +void ArgsDumper::visit(const StringSetArg & a) +{ + generic_visit(a); + + if (a.begin_allowed_args() != a.end_allowed_args()) + for (StringSetArg::AllowedArgConstIterator it = a.begin_allowed_args(), it_end = a.end_allowed_args(); + it != it_end; ++it) + { + std::stringstream p; + p << " " << (*it).first; + if (p.str().length() < 26) + p << std::string(26 - p.str().length(), ' '); + _os << p.str(); + _os << " " << (*it).second; + _os << std::endl; + } +} + +void ArgsDumper::visit(const EnumArg & a) +{ + generic_visit(a); + + for (EnumArg::AllowedArgConstIterator it = a.begin_allowed_args(), it_end = a.end_allowed_args(); + it != it_end; ++it) + { + std::stringstream p; + p << " " << (*it).first; + if (p.str().length() < 26) + p << std::string(26 - p.str().length(), ' '); + _os << p.str(); + _os << " " << (*it).second; + if ((*it).first == a.default_arg()) + _os << " (default)"; + _os << std::endl; + } +} + +void +ArgsDumper::visit(const SwitchArg & a) +{ + generic_visit(a); +} + +void +ArgsDumper::visit(const StringArg & a) +{ + generic_visit(a); +} + +void +ArgsDumper::visit(const IntegerArg & a) +{ + generic_visit(a); +} + +void +ArgsDumper::visit(const AliasArg & a) +{ + generic_visit(a); +} + diff --git a/0.26.0_alpha1/paludis/args/args_dumper.hh b/0.26.0_alpha1/paludis/args/args_dumper.hh new file mode 100644 index 000000000..60a7f2723 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_dumper.hh @@ -0,0 +1,88 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Stephen Bennett <spb@gentoo.org> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License, version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_ARGS_ARGS_DUMPER_HH +#define PALUDIS_GUARD_PALUDIS_ARGS_ARGS_DUMPER_HH 1 + +#include <iosfwd> +#include <paludis/args/args_visitor.hh> +#include <paludis/util/visitor.hh> + +/** \file + * Declarations for the ArgsDumper class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + class ArgsOption; + class SwitchArg; + class StringArg; + class IntegerArg; + class AliasArg; + class EnumArg; + + /** + * Prints help text appropriate to each command line option. + * + * \ingroup g_args + */ + class PALUDIS_VISIBLE ArgsDumper : + public ConstVisitor<ArgsVisitorTypes> + { + private: + std::ostream & _os; + + void generic_visit(const ArgsOption &); + + public: + /** + * Constructor. + */ + ArgsDumper(std::ostream & os); + + /// Visit a SwitchArg. + void visit(const SwitchArg &); + + /// Visit a StringArg. + void visit(const StringArg &); + + /// Visit an IntegerArg. + void visit(const IntegerArg &); + + /// Visit an AliasArg. + void visit(const AliasArg &); + + /// Visit an EnumArg. + void visit(const EnumArg &); + + /// Visit a StringSetArg. + void visit(const StringSetArg &); + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/args_error.cc b/0.26.0_alpha1/paludis/args/args_error.cc new file mode 100644 index 000000000..8b8a7a098 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_error.cc @@ -0,0 +1,38 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "args_error.hh" + +using namespace paludis::args; + +ArgsError::ArgsError(const std::string & our_message) throw () : + paludis::Exception("Error handling command line: " + our_message) +{ +} + +BadValue::BadValue(const std::string& option, const std::string& value) throw () : + ArgsError("Invalid parameter '" + value + "' for argument '" + option + "'") +{ +} + +MissingValue::MissingValue(const std::string & arg) throw() : + ArgsError("No parameter given for '" + arg + "'") +{ +} + diff --git a/0.26.0_alpha1/paludis/args/args_error.hh b/0.26.0_alpha1/paludis/args/args_error.hh new file mode 100644 index 000000000..aa96fc880 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_error.hh @@ -0,0 +1,91 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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_ARGS_ARGS_ERROR_HH +#define PALUDIS_GUARD_ARGS_ARGS_ERROR_HH 1 + +#include <paludis/util/exception.hh> +#include <string> + +/** \file + * Declarations for argument exception classes. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * Thrown if an invalid command line argument is provided. + * + * \ingroup g_exceptions + * \ingroup g_args + */ + class PALUDIS_VISIBLE ArgsError : + public paludis::Exception + { + protected: + /** + * Constructor. + */ + ArgsError(const std::string & message) throw (); + }; + + /** + * Thrown if an invalid parameter is passed to a valid command line argument. + * + * \ingroup g_args + * \ingroup g_exceptions + */ + class PALUDIS_VISIBLE BadValue : + public ArgsError + { + public: + /** + * Constructor + */ + BadValue(const std::string& option, const std::string& value) throw(); + }; + + /** + * Thrown if an argument is specified that needs a parameter, + * but no parameter is given. + * + * \ingroup g_args + * \ingroup g_exceptions + */ + class PALUDIS_VISIBLE MissingValue : + public ArgsError + { + public: + /** + * Constructor. + */ + MissingValue(const std::string & arg) throw (); + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/args_group.cc b/0.26.0_alpha1/paludis/args/args_group.cc new file mode 100644 index 000000000..1198542b9 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_group.cc @@ -0,0 +1,78 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "args.hh" +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <list> + +using namespace paludis::args; + +namespace paludis +{ + /** + * Implementation data for ArgsGroup. + * + * \ingroup grplibpaludisargs + */ + template<> + struct Implementation<ArgsGroup> + { + std::list<ArgsOption *> args_options; + }; +} + +ArgsGroup::ArgsGroup(ArgsHandler * h, const std::string & our_name, + const std::string & our_description) : + PrivateImplementationPattern<ArgsGroup>(new Implementation<ArgsGroup>), + _name(our_name), + _description(our_description), + _handler(h) +{ + h->add(this); +} + +void +ArgsGroup::add(ArgsOption * const value) +{ + /// \bug Should check for uniqueness of short and long names. + _imp->args_options.push_back(value); +} + +void +ArgsGroup::remove(ArgsOption * const value) +{ + _imp->args_options.remove(value); +} + +ArgsGroup::~ArgsGroup() +{ +} + +ArgsGroup::ConstIterator +ArgsGroup::begin() const +{ + return ConstIterator(_imp->args_options.begin()); +} + +ArgsGroup::ConstIterator +ArgsGroup::end() const +{ + return ConstIterator(_imp->args_options.end()); +} + diff --git a/0.26.0_alpha1/paludis/args/args_group.hh b/0.26.0_alpha1/paludis/args/args_group.hh new file mode 100644 index 000000000..ca4f8469e --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_group.hh @@ -0,0 +1,131 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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_ARGS_ARGS_GROUP_HH +#define PALUDIS_GUARD_ARGS_ARGS_GROUP_HH 1 + +#include <paludis/args/args_option.hh> +#include <paludis/util/instantiation_policy.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <string> + +#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh> + +/** \file + * Declarations for ArgsGroup. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + + namespace args + { + class ArgsHandler; + + /** + * Contains a related group of command line arguments. + * + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE ArgsGroup : + private PrivateImplementationPattern<ArgsGroup>, + private InstantiationPolicy<ArgsGroup, instantiation_method::NonCopyableTag> + { + private: + const std::string _name; + const std::string _description; + + ArgsHandler * _handler; + + public: + /** + * Fetch our handler. + */ + ArgsHandler * handler() + { + return _handler; + } + + /** + * Add an ArgsOption instance (called by the ArgsOption + * constructor). + */ + void add(ArgsOption * const value); + + /** + * Remove an ArgsOption instance (called by + * ArgsOption::remove). + */ + void remove(ArgsOption * const value); + + ///\name Iterate over our ArgsOptions. + ///\{ + + typedef libwrapiter::ForwardIterator<ArgsGroup, ArgsOption * const> ConstIterator; + + ConstIterator begin() const; + ConstIterator end() const; + + ///\} + + ///\name Basic operations + ///\{ + + ArgsGroup(ArgsHandler * h, const std::string & name, + const std::string & description); + + ~ArgsGroup(); + + ///\} + + /** + * Fetch our name. + */ + const std::string & name() const + { + return _name; + } + + /** + * Fetch our description. + */ + const std::string & description() const + { + return _description; + } + + /** + * Fetch our handler. + */ + ArgsHandler * handler() const + { + return _handler; + } + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/args_handler.cc b/0.26.0_alpha1/paludis/args/args_handler.cc new file mode 100644 index 000000000..ef1a2c4da --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_handler.cc @@ -0,0 +1,254 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "args.hh" +#include "args_dumper.hh" +#include <paludis/util/system.hh> +#include <paludis/util/join.hh> +#include <paludis/util/iterator.hh> +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <paludis/util/visitor-impl.hh> +#include <algorithm> +#include <sstream> +#include <list> +#include <map> + +using namespace paludis::args; + +namespace paludis +{ + /** + * Implementation data for ArgsHandler. + * + * \ingroup grplibpaludisargs + */ + template<> + struct Implementation<ArgsHandler> + { + std::list<ArgsGroup *> groups; + std::list<std::string> parameters; + std::list<std::string> usage_lines; + std::list<std::pair<std::string, std::string> > environment_lines; + + std::map<std::string, ArgsOption *> longopts; + std::map<char, ArgsOption *> shortopts; + }; +} + +ArgsHandler::ArgsHandler() : + PrivateImplementationPattern<ArgsHandler>(new Implementation<ArgsHandler>) +{ +} + +ArgsHandler::~ArgsHandler() +{ +} + +void +ArgsHandler::add_usage_line(const std::string & l) +{ + _imp->usage_lines.push_back(l); +} + +void +ArgsHandler::add_environment_variable(const std::string & e, const std::string & desc) +{ + _imp->environment_lines.push_back(std::make_pair(e, desc)); +} + +void +ArgsHandler::add(ArgsGroup * const g) +{ + /// \bug Should check for name uniqueness. + _imp->groups.push_back(g); +} + +void +ArgsHandler::run(const int argc, const char * const * const argv, const std::string & env_var, + const std::string & env_prefix) +{ + run(argc, argv, "", env_var, env_prefix); +} + +void +ArgsHandler::run(const int argc, const char * const * const argv, + const std::string & client, + const std::string & env_var, + const std::string & env_prefix) +{ + std::list<std::string> args; + std::string env_options; + + setenv("PALUDIS_CLIENT", client.c_str(), 1); + + if (! env_var.empty()) + env_options = paludis::getenv_with_default(env_var, ""); + + std::istringstream iss(env_options); + std::string option; + while (iss.good()) + { + iss >> option; + if (!option.empty()) + args.push_back(option); + } + + args.insert(args.end(), &argv[1], &argv[argc]); + + libwrapiter::ForwardIterator<ArgsVisitor, std::string> argit(args.begin()), arge(args.end()); + + ArgsVisitor visitor(&argit, arge, env_prefix); + + for ( ; argit != arge; ++argit ) + { + std::string arg = *argit; + + if (arg == "--") + { + ++argit; + break; + } + else if (0 == arg.compare(0, 2, "--")) + { + arg.erase(0, 2); + std::map<std::string, ArgsOption *>::iterator it = _imp->longopts.find(arg); + if (it == _imp->longopts.end()) + throw BadArgument("--" + arg); + it->second->accept(visitor); + } + else if (arg[0] == '-') + { + arg.erase(0, 1); + for (std::string::iterator c = arg.begin(); c != arg.end(); ++c) + { + std::map<char, ArgsOption *>::iterator it = _imp->shortopts.find(*c); + if (it == _imp->shortopts.end()) + { + throw BadArgument(std::string("-") + *c); + } + it->second->accept(visitor); + } + } + else + { + _imp->parameters.push_back(arg); + } + } + + _imp->parameters.insert(_imp->parameters.end(), + argit, libwrapiter::ForwardIterator<ArgsVisitor, std::string>(args.end())); + + if (! env_prefix.empty()) + setenv((env_prefix + "_PARAMS").c_str(), join(_imp->parameters.begin(), + _imp->parameters.end(), " ").c_str(), 1); +} + +void +ArgsHandler::dump_to_stream(std::ostream & s) const +{ + ArgsDumper dump(s); + std::list<ArgsGroup *>::const_iterator g(_imp->groups.begin()), g_end(_imp->groups.end()); + for ( ; g != g_end ; ++g) + { + s << (*g)->name() << ":" << std::endl; + + std::for_each(indirect_iterator((*g)->begin()), indirect_iterator((*g)->end()), accept_visitor(dump)); + + s << std::endl; + } +} + +ArgsHandler::ParametersConstIterator +ArgsHandler::begin_parameters() const +{ + return ParametersConstIterator(_imp->parameters.begin()); +} + +ArgsHandler::ParametersConstIterator +ArgsHandler::end_parameters() const +{ + return ParametersConstIterator(_imp->parameters.end()); +} + +bool +ArgsHandler::empty() const +{ + return _imp->parameters.empty(); +} + +std::ostream & +paludis::args::operator<< (std::ostream & s, const ArgsHandler & h) +{ + h.dump_to_stream(s); + return s; +} + +void +ArgsHandler::add_option(ArgsOption * const opt, const std::string & long_name, + const char short_name) +{ + _imp->longopts[long_name] = opt; + if (short_name != '\0') + _imp->shortopts[short_name] = opt; +} + +void +ArgsHandler::remove_option(const std::string & long_name, const char short_name) +{ + _imp->longopts.erase(long_name); + if (short_name != '\0') + _imp->shortopts.erase(short_name); +} + +ArgsHandler::UsageLineConstIterator +ArgsHandler::begin_usage_lines() const +{ + return UsageLineConstIterator(_imp->usage_lines.begin()); +} + +ArgsHandler::UsageLineConstIterator +ArgsHandler::end_usage_lines() const +{ + return UsageLineConstIterator(_imp->usage_lines.end()); +} + +ArgsHandler::EnvironmentLineConstIterator +ArgsHandler::begin_environment_lines() const +{ + return EnvironmentLineConstIterator(_imp->environment_lines.begin()); +} + +ArgsHandler::EnvironmentLineConstIterator +ArgsHandler::end_environment_lines() const +{ + return EnvironmentLineConstIterator(_imp->environment_lines.end()); +} + +ArgsHandler::ArgsGroupsConstIterator +ArgsHandler::begin_args_groups() const +{ + return ArgsGroupsConstIterator(_imp->groups.begin()); +} + +ArgsHandler::ArgsGroupsConstIterator +ArgsHandler::end_args_groups() const +{ + return ArgsGroupsConstIterator(_imp->groups.end()); +} + diff --git a/0.26.0_alpha1/paludis/args/args_handler.hh b/0.26.0_alpha1/paludis/args/args_handler.hh new file mode 100644 index 000000000..ac4fb7547 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_handler.hh @@ -0,0 +1,203 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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_ARGS_ARGS_HANDLER_HH +#define PALUDIS_GUARD_ARGS_ARGS_HANDLER_HH 1 + +#include <paludis/args/args_group.hh> +#include <paludis/util/instantiation_policy.hh> +#include <paludis/util/private_implementation_pattern.hh> + +#include <iosfwd> +#include <string> + +#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh> + +/** \file + * Declarations for ArgsHandler. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * Handles command line arguments. + * + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE ArgsHandler : + private InstantiationPolicy<ArgsHandler, instantiation_method::NonCopyableTag>, + private PrivateImplementationPattern<ArgsHandler> + { + friend class ArgsGroup; + friend std::ostream & operator<< (std::ostream &, const ArgsHandler &); + + protected: + /** + * Add a new usage line. + */ + void add_usage_line(const std::string & l); + + /** + * Add a new environment line. + */ + void add_environment_variable(const std::string & e, const std::string & desc); + + /** + * Add an new ArgsGroup (called by the ArgsGroup constructor). + */ + void add(ArgsGroup * const); + + /** + * Dump, for --help output (called by operator<<). + */ + void dump_to_stream(std::ostream & s) const; + + public: + ///\name Basic operations + ///\{ + + ArgsHandler(); + + virtual ~ArgsHandler(); + + ///\} + + /** + * \deprecated Use the five arg form. + */ + void run(const int, const char * const * const, const std::string & env_var = "", + const std::string & env_prefix = "") PALUDIS_ATTRIBUTE((deprecated)); + + /** + * Parse command line arguments. The third argument is used to + * set PALUDIS_CLIENT. The fourth argument is the name of an + * environment variable holding arguments which are prepended + * to the command line arguments. The fifth argument is used as + * a prefix to export our command line via the environment. + */ + virtual void run(const int, const char * const * const, + const std::string & client, const std::string & env_var, + const std::string & env_prefix); + + ///\name Iterate over our parameters (non - and -- switches and their values) + ///\{ + + typedef libwrapiter::ForwardIterator<ArgsHandler, const std::string> ParametersConstIterator; + + ParametersConstIterator begin_parameters() const; + + ParametersConstIterator end_parameters() const; + + bool empty() const; + + ///\} + + /** + * Add an ArgsOption instance. + */ + void add_option(ArgsOption * const, const std::string & long_name, + const char short_name = '\0'); + + /** + * Remove an ArgsOption instance. + */ + void remove_option(const std::string & long_name, const char short_name = '\0'); + + ///\name About our application (for documentation) + ///\{ + + /** + * What is our application name? + */ + virtual std::string app_name() const = 0; + + /** + * What is our application's Unix manual section? + */ + virtual std::string man_section() const + { + return "1"; + } + + /** + * One line synopsis of what our application is. + */ + virtual std::string app_synopsis() const = 0; + + /** + * Long description of what our application is. + */ + virtual std::string app_description() const = 0; + + ///\} + + ///\name Iterate over our usage lines (for documentation) + ///\{ + + typedef libwrapiter::ForwardIterator<ArgsHandler, const std::string> UsageLineConstIterator; + + UsageLineConstIterator begin_usage_lines() const; + + UsageLineConstIterator end_usage_lines() const; + + ///\} + + ///\name Iterate over our environment lines (for documentation) + ///\{ + + typedef libwrapiter::ForwardIterator<ArgsHandler, + const std::pair<std::string, std::string> > EnvironmentLineConstIterator; + + EnvironmentLineConstIterator begin_environment_lines() const; + + EnvironmentLineConstIterator end_environment_lines() const; + + ///\} + + ///\name Iterate over our groups + ///\{ + + typedef libwrapiter::ForwardIterator<ArgsHandler, ArgsGroup * const> ArgsGroupsConstIterator; + + ArgsGroupsConstIterator begin_args_groups() const; + + ArgsGroupsConstIterator end_args_groups() const; + + ///\} + }; + + /** + * Output an ArgsHandler to an ostream, for --help output. + * + * \ingroup g_args + */ + std::ostream & operator<< (std::ostream &, const ArgsHandler &) PALUDIS_VISIBLE; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/args_option.cc b/0.26.0_alpha1/paludis/args/args_option.cc new file mode 100644 index 000000000..3f2f0938e --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_option.cc @@ -0,0 +1,310 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "args.hh" +#include "args_error.hh" +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <set> +#include <vector> +#include <algorithm> + +using namespace paludis; +using namespace paludis::args; + +namespace +{ + struct ArgIs + { + /// The argument. + const std::string arg; + + /// Constructor. + ArgIs(const std::string & a) : + arg(a) + { + } + + /// Comparator. + bool operator() (const std::pair<std::string, std::string> & p) const + { + return p.first == arg; + } + }; +} + +ArgsOption::ArgsOption(ArgsGroup * const g, const std::string & our_long_name, + const char our_short_name, const std::string & our_description) : + _group(g), + _long_name(our_long_name), + _short_name(our_short_name), + _description(our_description), + _specified(false) +{ + g->add(this); + g->handler()->add_option(this, our_long_name, our_short_name); +} + +ArgsOption::~ArgsOption() +{ +} + +void +ArgsOption::remove() +{ + _group->remove(this); + _group->handler()->remove_option(_long_name, _short_name); +} + +SwitchArg::SwitchArg(ArgsGroup * const our_group, std::string our_long_name, char our_short_name, + std::string our_description) : + ArgsOption(our_group, our_long_name, our_short_name, our_description) +{ +} + +SwitchArg::~SwitchArg() +{ +} + +AliasArg::AliasArg(ArgsOption * const o, const std::string & our_long_name) : + ArgsOption(o->group(), our_long_name, '\0', "Alias for --" + o->long_name()), + _other(o) +{ + o->group()->handler()->add_option(o, our_long_name); +} + +StringArg::StringArg(ArgsGroup * const g, const std::string & our_long_name, + const char our_short_name, const std::string & our_description) : + ArgsOption(g, our_long_name, our_short_name, our_description), + _validator(0) +{ +} + +StringArg::StringArg(ArgsGroup * const g, const std::string & our_long_name, + const char our_short_name, const std::string & our_description, + void (* v) (const std::string &)) : + ArgsOption(g, our_long_name, our_short_name, our_description), + _validator(v) +{ +} + +namespace paludis +{ + template<> + struct Implementation<StringSetArg> + { + std::set<std::string> args; + std::vector<std::pair<std::string, std::string> > allowed_args; + }; + + template<> + struct Implementation<StringSetArg::StringSetArgOptions> + { + std::vector<std::pair<std::string, std::string> > options; + }; +} + +StringSetArg::StringSetArg(ArgsGroup * const g, const std::string & our_long_name, + const char our_short_name, const std::string & our_description, + const StringSetArgOptions & opts) : + ArgsOption(g, our_long_name, our_short_name, our_description), + PrivateImplementationPattern<StringSetArg>(new Implementation<StringSetArg>), + _validator(0) +{ + std::copy(opts._imp->options.begin(), opts._imp->options.end(), + std::back_inserter(_imp->allowed_args)); +} + +StringSetArg::StringSetArg(ArgsGroup * const g, const std::string & our_long_name, + const char our_short_name, const std::string & our_description, + const StringSetArgOptions & opts, void (* v) (const std::string &)) : + ArgsOption(g, our_long_name, our_short_name, our_description), + PrivateImplementationPattern<StringSetArg>(new Implementation<StringSetArg>), + _validator(v) +{ + std::copy(opts._imp->options.begin(), opts._imp->options.end(), + std::back_inserter(_imp->allowed_args)); +} + +StringSetArg::ConstIterator +StringSetArg::begin_args() const +{ + return ConstIterator(_imp->args.begin()); +} + +StringSetArg::ConstIterator +StringSetArg::end_args() const +{ + return ConstIterator(_imp->args.end()); +} + +void +StringSetArg::add_argument(const std::string & arg) +{ + Context context("When handling argument '" + arg + "' for '--" + long_name() + "':"); + + if (! _imp->allowed_args.empty()) + if (_imp->allowed_args.end() == std::find_if(_imp->allowed_args.begin(), + _imp->allowed_args.end(), ArgIs(arg))) + throw (BadValue("--" + long_name(), arg)); + + if (_validator) + (*_validator)(arg); + + _imp->args.insert(arg); +} + +IntegerArg::IntegerArg(ArgsGroup * const our_group, const std::string & our_long_name, + char our_short_name, const std::string & our_description) : + ArgsOption(our_group, our_long_name, our_short_name, our_description) +{ +} + +namespace paludis +{ + template<> + struct Implementation<EnumArg> + { + std::vector<std::pair<std::string, std::string> > allowed_args; + }; + + template<> + struct Implementation<EnumArg::EnumArgOptions> + { + std::vector<std::pair<std::string, std::string> > options; + }; +} + +StringSetArg::StringSetArgOptions::StringSetArgOptions(std::string opt, std::string desc) : + PrivateImplementationPattern<StringSetArgOptions>(new Implementation<StringSetArgOptions>) +{ + _imp->options.push_back(std::make_pair(opt, desc)); +} + +StringSetArg::StringSetArgOptions & +StringSetArg::StringSetArgOptions::operator() (std::string opt, std::string desc) +{ + _imp->options.push_back(std::make_pair(opt, desc)); + return *this; +} + +StringSetArg::StringSetArgOptions::StringSetArgOptions(const StringSetArg::StringSetArgOptions & o) : + PrivateImplementationPattern<StringSetArgOptions>(new Implementation<StringSetArgOptions>) +{ + std::copy(o._imp->options.begin(), o._imp->options.end(), + std::back_inserter(_imp->options)); +} + +StringSetArg::StringSetArgOptions::~StringSetArgOptions() +{ +} + +StringSetArg::StringSetArgOptions::StringSetArgOptions() : + PrivateImplementationPattern<StringSetArgOptions>(new Implementation<StringSetArgOptions>) +{ +} + +void +EnumArg::set_argument(const std::string & arg) +{ + Context context("When handling argument '" + arg + "' for '--" + long_name() + "':"); + + if (_imp->allowed_args.end() == std::find_if(_imp->allowed_args.begin(), + _imp->allowed_args.end(), ArgIs(arg))) + throw (BadValue("--" + long_name(), arg)); + + _argument = arg; +} + +void +StringArg::set_argument(const std::string & arg) +{ + Context context("When handling argument '" + arg + "' for '--" + long_name() + "':"); + + if (_validator) + (*_validator)(arg); + + _argument = arg; +} + +EnumArg::~EnumArg() +{ +} + +EnumArg::EnumArgOptions::EnumArgOptions(std::string opt, std::string desc) : + PrivateImplementationPattern<EnumArgOptions>(new Implementation<EnumArgOptions>) +{ + _imp->options.push_back(std::make_pair(opt, desc)); +} + +EnumArg::EnumArgOptions & EnumArg::EnumArgOptions::operator() (std::string opt, std::string desc) +{ + _imp->options.push_back(std::make_pair(opt, desc)); + return *this; +} + +EnumArg::EnumArgOptions::~EnumArgOptions() +{ +} + +EnumArg::EnumArg(ArgsGroup * const our_group, const std::string & our_long_name, + const char our_short_name, const std::string & our_description, + const EnumArgOptions & opts, const std::string & our_default_arg) : + ArgsOption(our_group, our_long_name, our_short_name, our_description), + PrivateImplementationPattern<EnumArg>(new Implementation<EnumArg>), + _argument(our_default_arg), + _default_arg(our_default_arg) +{ + _imp->allowed_args = opts._imp->options; +} + +void +EnumArg::set_default_arg(const std::string & arg) +{ + _argument = arg; + _default_arg = arg; +} + +EnumArg::AllowedArgConstIterator +EnumArg::begin_allowed_args() const +{ + return AllowedArgConstIterator(_imp->allowed_args.begin()); +} + +EnumArg::AllowedArgConstIterator +EnumArg::end_allowed_args() const +{ + return AllowedArgConstIterator(_imp->allowed_args.end()); +} + +StringSetArg::~StringSetArg() +{ +} + +StringSetArg::AllowedArgConstIterator +StringSetArg::begin_allowed_args() const +{ + return AllowedArgConstIterator(_imp->allowed_args.begin()); +} + +StringSetArg::AllowedArgConstIterator +StringSetArg::end_allowed_args() const +{ + return AllowedArgConstIterator(_imp->allowed_args.end()); +} + diff --git a/0.26.0_alpha1/paludis/args/args_option.hh b/0.26.0_alpha1/paludis/args/args_option.hh new file mode 100644 index 000000000..f0f500c8e --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_option.hh @@ -0,0 +1,453 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * Copyright (c) 2006 Stephen Bennett <spb@gentoo.org> + * + * 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_ARGS_ARGS_OPTION_HH +#define PALUDIS_GUARD_ARGS_ARGS_OPTION_HH 1 + +#include <paludis/args/args_visitor.hh> +#include <paludis/util/private_implementation_pattern.hh> + +/** \file + * Declarations for ArgsOption. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + class ArgsGroup; + + /** + * Base class for a command line option. + * + * \ingroup g_args + */ + class PALUDIS_VISIBLE ArgsOption : + public virtual AcceptInterface<ArgsVisitorTypes> + { + friend class ArgsHandler; + + private: + ArgsGroup * const _group; + + const std::string _long_name; + const char _short_name; + const std::string _description; + + bool _specified; + + ArgsOption(const ArgsOption &); + void operator= (const ArgsOption &); + + protected: + /** + * Constructor. + */ + ArgsOption(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description); + + /** + * Destructor. + */ + virtual ~ArgsOption(); + + public: + /** + * Remove this option. + */ + void remove(); + + /** + * Fetch our long name. + */ + const std::string & long_name() const + { + return _long_name; + } + + /** + * Fetch our short name (may be 0). + */ + char short_name() const + { + return _short_name; + } + + /** + * Fetch our description. + */ + const std::string & description() const + { + return _description; + } + + /** + * Fetch whether or not we were specified on the + * command line. + */ + virtual bool specified() const + { + return _specified; + } + + /** + * Set the value returned by specified(). + */ + virtual void set_specified(const bool value) + { + _specified = value; + } + + /** + * Fetch our group. + */ + ArgsGroup * group() + { + return _group; + } + }; + + /** + * A SwitchArg is an option that can either be specified or not + * specified, and that takes no value (for example, --help). + * + * \ingroup g_args + */ + class PALUDIS_VISIBLE SwitchArg : + public ArgsOption, + public AcceptInterfaceVisitsThis<ArgsVisitorTypes, SwitchArg> + { + public: + /** + * Constructor. + */ + SwitchArg(ArgsGroup * const group, std::string long_name, char short_name, + std::string description); + + ~SwitchArg(); + }; + + /** + * An option that takes a string argument. + * + * \ingroup g_args + */ + class PALUDIS_VISIBLE StringArg : + public ArgsOption, + public AcceptInterfaceVisitsThis<ArgsVisitorTypes, StringArg> + { + private: + std::string _argument; + void (* _validator) (const std::string &); + + public: + /** + * Constructor + */ + StringArg(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description); + + /** + * Constructor with validator. + */ + StringArg(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description, + void (* validator) (const std::string &)); + + /** + * Fetch the argument that was given to this option. + */ + const std::string& argument() const { return _argument; } + + /** + * Set the argument returned by argument(). + */ + void set_argument(const std::string& arg); + }; + + /** + * An option that takes a set of strings. + * + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE StringSetArg : + public ArgsOption, + public AcceptInterfaceVisitsThis<ArgsVisitorTypes, StringSetArg>, + private PrivateImplementationPattern<StringSetArg> + { + private: + void (* _validator) (const std::string &); + + public: + /** + * Helper class for passing available options and associated descriptions + * to the StringSetArg constructor. + * + * \ingroup grplibpaludisargs + */ + class PALUDIS_VISIBLE StringSetArgOptions : + private PrivateImplementationPattern<StringSetArgOptions> + { + friend class StringSetArg; + + public: + /** + * Constructor + */ + StringSetArgOptions(const std::string, const std::string); + + /** + * Blank constructor + */ + explicit StringSetArgOptions(); + + /** + * Copy constructor + */ + StringSetArgOptions(const StringSetArgOptions &); + + /** + * Destructor. + */ + ~StringSetArgOptions(); + + /** + * Adds another (option, description) pair. + */ + StringSetArgOptions & operator() (const std::string, const std::string); + }; + + ///\name Basic operations + ///\{ + + StringSetArg(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description, + const StringSetArgOptions & options = StringSetArgOptions()); + + StringSetArg(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description, + const StringSetArgOptions & options, + void (* validator) (const std::string &)); + + ~StringSetArg(); + + ///\} + + ///\name Iterate over our args. + ///\{ + + typedef libwrapiter::ForwardIterator<StringArg, const std::string> ConstIterator; + + ConstIterator begin_args() const; + + ConstIterator end_args() const; + + ///\} + + /** + * Add an argument to the set. + */ + void add_argument(const std::string & arg); + + ///\name Iterate over our allowed arguments and associated descriptions + ///\{ + + typedef libwrapiter::ForwardIterator<StringSetArg, + const std::pair<std::string, std::string> > AllowedArgConstIterator; + + AllowedArgConstIterator begin_allowed_args() const; + + AllowedArgConstIterator end_allowed_args() const; + + ///\} + }; + + + /** + * An AliasArg is an alias for another argument. + * + * \ingroup g_args + */ + class PALUDIS_VISIBLE AliasArg : + public ArgsOption, + public AcceptInterfaceVisitsThis<ArgsVisitorTypes, AliasArg> + { + private: + ArgsOption * const _other; + + public: + /** + * Constructor. + */ + AliasArg(ArgsOption * const other, const std::string & new_long_name); + + virtual bool specified() const + { + return _other->specified(); + } + + virtual void set_specified(const bool value) + { + _other->set_specified(value); + } + + /** + * Fetch our associated option. + */ + ArgsOption * other() const + { + return _other; + } + }; + + /** + * An option that takes an integer argument. + * + * \ingroup grplibpaludisargs + */ + class PALUDIS_VISIBLE IntegerArg : + public ArgsOption, + public AcceptInterfaceVisitsThis<ArgsVisitorTypes, IntegerArg> + { + private: + int _argument; + + public: + /** + * Constructor + */ + IntegerArg(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description); + /** + * Fetch the argument that was given to this option. + */ + int argument() const { return _argument; } + + /** + * Set the argument returned by argument(). + */ + void set_argument(const int arg) { _argument = arg; } + }; + + /** + * An option that takes one of a predefined set of string arguments. + * + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE EnumArg : + public ArgsOption, + public AcceptInterfaceVisitsThis<ArgsVisitorTypes, EnumArg>, + private PrivateImplementationPattern<EnumArg> + { + private: + std::string _argument; + std::string _default_arg; + + public: + /** + * Helper class for passing available options and associated descriptions + * to the EnumArg constructor. + * + * \ingroup grplibpaludisargs + */ + class PALUDIS_VISIBLE EnumArgOptions : + private PrivateImplementationPattern<EnumArgOptions> + { + friend class EnumArg; + + public: + /** + * Constructor + */ + EnumArgOptions(const std::string, const std::string); + + /** + * Destructor. + */ + ~EnumArgOptions(); + + /** + * Adds another (option, description) pair. + */ + EnumArgOptions & operator() (const std::string, const std::string); + }; + + /** + * Constructor. + */ + EnumArg(ArgsGroup * const group, const std::string & long_name, + const char short_name, const std::string & description, + const EnumArgOptions & opts, const std::string & default_arg); + + ~EnumArg(); + + /** + * Fetch the argument that was given to this option. + */ + const std::string & argument() const + { + return _argument; + } + + /** + * Set the argument returned by argument(), having verified that + * it is one of the arguments allowed for this option. + */ + void set_argument(const std::string & arg); + + /** + * Change the default option (should be called before + * set_argument()). + */ + void set_default_arg(const std::string & arg); + + /** + * Fetch the default option, as specified to the + * constructor or set_default_arg(). + */ + const std::string & default_arg() const + { + return _default_arg; + } + + ///\name Iterate over our allowed arguments and associated descriptions + ///\{ + + typedef libwrapiter::ForwardIterator<EnumArg, + const std::pair<std::string, std::string> > AllowedArgConstIterator; + + AllowedArgConstIterator begin_allowed_args() const; + + AllowedArgConstIterator end_allowed_args() const; + + ///\} + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/args_visitor.cc b/0.26.0_alpha1/paludis/args/args_visitor.cc new file mode 100644 index 000000000..3c2fb6b95 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_visitor.cc @@ -0,0 +1,162 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ +/* + * Copyright (c) 2005, 2006, 2007 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 "args_option.hh" +#include "args_error.hh" + +#include <paludis/util/visitor.hh> +#include <paludis/util/visitor-impl.hh> +#include <paludis/util/destringify.hh> +#include <paludis/util/system.hh> +#include <paludis/util/join.hh> + +#include <algorithm> +#include <sstream> +#include <stdlib.h> + +using namespace paludis; +using namespace paludis::args; + +template class Visitor<ArgsVisitorTypes>; +template class AcceptInterface<ArgsVisitorTypes>; + +template class AcceptInterfaceVisitsThis<ArgsVisitorTypes, IntegerArg>; +template class AcceptInterfaceVisitsThis<ArgsVisitorTypes, EnumArg>; +template class AcceptInterfaceVisitsThis<ArgsVisitorTypes, StringArg>; +template class AcceptInterfaceVisitsThis<ArgsVisitorTypes, StringSetArg>; +template class AcceptInterfaceVisitsThis<ArgsVisitorTypes, AliasArg>; +template class AcceptInterfaceVisitsThis<ArgsVisitorTypes, SwitchArg>; + +template class Visits<IntegerArg>; +template class Visits<EnumArg>; +template class Visits<StringArg>; +template class Visits<StringSetArg>; +template class Visits<AliasArg>; +template class Visits<SwitchArg>; + +template class Visits<const IntegerArg>; +template class Visits<const EnumArg>; +template class Visits<const StringArg>; +template class Visits<const StringSetArg>; +template class Visits<const AliasArg>; +template class Visits<const SwitchArg>; + +ArgsVisitor::ArgsVisitor(libwrapiter::ForwardIterator<ArgsVisitor, std::string> * ai, + libwrapiter::ForwardIterator<ArgsVisitor, std::string> ae, + const std::string & env_prefix) : + _args_index(ai), + _args_end(ae), + _env_prefix(env_prefix) +{ +} + +const std::string & +ArgsVisitor::get_param(const ArgsOption & arg) +{ + if (++(*_args_index) == _args_end) + throw MissingValue("--" + arg.long_name()); + + return **_args_index; +} + +void ArgsVisitor::visit(StringArg & arg) +{ + arg.set_specified(true); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), "1", 1); + + std::string p(get_param(arg)); + arg.set_argument(p); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), p.c_str(), 1); +} + +void ArgsVisitor::visit(AliasArg & arg) +{ + arg.other()->accept(*this); +} + +void ArgsVisitor::visit(SwitchArg & arg) +{ + arg.set_specified(true); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), "1", 1); +} + +void ArgsVisitor::visit(IntegerArg & arg) +{ + arg.set_specified(true); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), "1", 1); + + std::string param = get_param(arg); + try + { + int a(destringify<int>(param)); + arg.set_argument(a); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), stringify(a).c_str(), 1); + } + catch (const DestringifyError &) + { + throw BadValue("--" + arg.long_name(), param); + } +} + +void ArgsVisitor::visit(EnumArg & arg) +{ + arg.set_specified(true); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), "1", 1); + + std::string p(get_param(arg)); + arg.set_argument(p); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), p.c_str(), 1); +} + +void ArgsVisitor::visit(StringSetArg & arg) +{ + arg.set_specified(true); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), "1", 1); + + std::string param = get_param(arg); + arg.add_argument(param); + + if (! _env_prefix.empty()) + setenv(env_name(arg.long_name()).c_str(), join(arg.begin_args(), + arg.end_args(), " ").c_str(), 1); +} + +std::string +ArgsVisitor::env_name(const std::string & long_name) const +{ + std::string result(_env_prefix + "_" + long_name); + std::replace(result.begin(), result.end(), '-', '_'); + return result; +} + diff --git a/0.26.0_alpha1/paludis/args/args_visitor.hh b/0.26.0_alpha1/paludis/args/args_visitor.hh new file mode 100644 index 000000000..1db4fbe0b --- /dev/null +++ b/0.26.0_alpha1/paludis/args/args_visitor.hh @@ -0,0 +1,115 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * Copyright (c) 2006 Stephen Bennett <spb@gentoo.org> + * + * 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_ARGS_ARGS_VISITOR_HH +#define PALUDIS_GUARD_ARGS_ARGS_VISITOR_HH 1 + +#include <paludis/util/visitor.hh> +#include <paludis/util/attributes.hh> +#include <string> + +#include <libwrapiter/libwrapiter_forward_iterator.hh> + +/** \file + * Declarations for ArgsVisitor. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + class ArgsOption; + class StringArg; + class AliasArg; + class SwitchArg; + class IntegerArg; + class EnumArg; + class StringSetArg; + + /** + * Visitor types for visitors that can visit Args. + * + * \ingroup g_args + */ + struct ArgsVisitorTypes : + VisitorTypes< + ArgsVisitorTypes, + ArgsOption, + StringArg, + AliasArg, + SwitchArg, + IntegerArg, + EnumArg, + StringSetArg> + { + }; + + /** + * Visitor class. Processes command-line options as they are found. + * + * \ingroup g_args + */ + class PALUDIS_VISIBLE ArgsVisitor : + public Visitor<ArgsVisitorTypes> + { + private: + libwrapiter::ForwardIterator<ArgsVisitor, std::string> * _args_index, _args_end; + std::string _env_prefix; + + const std::string & get_param(const ArgsOption &); + + std::string env_name(const std::string & long_name) const; + + public: + /** + * Constructor + */ + ArgsVisitor(libwrapiter::ForwardIterator<ArgsVisitor, std::string> *, + libwrapiter::ForwardIterator<ArgsVisitor, std::string>, + const std::string & env_prefix = ""); + + /// Visit a StringArg. + void visit(StringArg &); + + /// Visit an AliasArg. + void visit(AliasArg &); + + /// Visit a SwitchArg. + void visit(SwitchArg &); + + /// Visit an IntegerArg. + void visit(IntegerArg &); + + /// Visit an EnumArg. + void visit(EnumArg &); + + /// Visit a StringSetArg. + void visit(StringSetArg &); + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/bad_argument.cc b/0.26.0_alpha1/paludis/args/bad_argument.cc new file mode 100644 index 000000000..aff38b00c --- /dev/null +++ b/0.26.0_alpha1/paludis/args/bad_argument.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "bad_argument.hh" + +using namespace paludis::args; + +BadArgument::BadArgument(const std::string & option) throw () : + ArgsError("Bad argument '" + option + "'") +{ +} + diff --git a/0.26.0_alpha1/paludis/args/bad_argument.hh b/0.26.0_alpha1/paludis/args/bad_argument.hh new file mode 100644 index 000000000..4d09aed64 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/bad_argument.hh @@ -0,0 +1,57 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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_ARGS_BAD_ARGUMENT_HH +#define PALUDIS_GUARD_ARGS_BAD_ARGUMENT_HH 1 + +#include <paludis/args/args_error.hh> + +/** \file + * Declarations for BadArgument. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * Thrown if an unrecognised command line argument is specified. + * + * \ingroup g_args + * \ingroup g_exceptions + */ + class PALUDIS_VISIBLE BadArgument : + public ArgsError + { + public: + /** + * Constructor. + */ + BadArgument(const std::string & option) throw (); + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/checks_arg.cc b/0.26.0_alpha1/paludis/args/checks_arg.cc new file mode 100644 index 000000000..a1181e955 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/checks_arg.cc @@ -0,0 +1,52 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 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 "checks_arg.hh" +#include "do_help.hh" + +using namespace paludis; +using namespace paludis::args; + +ChecksArg::ChecksArg(ArgsGroup * const grp, const std::string & ln, char sh) : + EnumArg(grp, ln, sh, "Whether to run post-build checks", + EnumArgOptions + ("none", "Don't run checks, even if they should be run") + ("default", "Run checks if they should be run by default") + ("always", "Always run checks"), + "default") +{ +} + +ChecksArg::~ChecksArg() +{ +} + +InstallActionChecksOption +ChecksArg::option() const +{ + if ("none" == argument()) + return iaco_none; + if ("default" == argument()) + return iaco_default; + if ("always" == argument()) + return iaco_always; + + throw DoHelp("Bad value for --" + long_name()); +} + diff --git a/0.26.0_alpha1/paludis/args/checks_arg.hh b/0.26.0_alpha1/paludis/args/checks_arg.hh new file mode 100644 index 000000000..d6ecc9849 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/checks_arg.hh @@ -0,0 +1,67 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 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_COMMON_ARGS_CHECKS_ARG_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_CHECKS_ARG_HH 1 + +#include <paludis/args/args_option.hh> +#include <paludis/action-fwd.hh> + +/** \file + * Declarations for the Checks class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * The '--checks' standard command line argument. + * + * \since 0.26 + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE ChecksArg : + public EnumArg + { + public: + ///\name Basic operations + ///\{ + + ChecksArg(ArgsGroup * const, const std::string &, char); + ~ChecksArg(); + + ///\} + + /** + * Our selected value, as an InstallActionChecksOption. + */ + InstallActionChecksOption option() const; + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/debug_build_arg.cc b/0.26.0_alpha1/paludis/args/debug_build_arg.cc new file mode 100644 index 000000000..9a7fe1c22 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/debug_build_arg.cc @@ -0,0 +1,53 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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 "debug_build_arg.hh" +#include "do_help.hh" + +using namespace paludis; +using namespace paludis::args; + +DebugBuildArg::DebugBuildArg(ArgsGroup * const grp, const std::string & ln, + char sh) : + EnumArg(grp, ln, sh, "What to do with debug information", + EnumArgOptions + ("none", "Discard debug information") + ("split", "Split debug information") + ("internal", "Keep debug information"), + "none") +{ +} + +DebugBuildArg::~DebugBuildArg() +{ +} + +InstallActionDebugOption +DebugBuildArg::option() const +{ + if ("none" == argument()) + return iado_none; + if ("split" == argument()) + return iado_split; + if ("internal" == argument()) + return iado_internal; + + throw DoHelp("Bad value for --" + long_name()); +} + diff --git a/0.26.0_alpha1/paludis/args/debug_build_arg.hh b/0.26.0_alpha1/paludis/args/debug_build_arg.hh new file mode 100644 index 000000000..afe99fd8e --- /dev/null +++ b/0.26.0_alpha1/paludis/args/debug_build_arg.hh @@ -0,0 +1,67 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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_COMMON_ARGS_DEBUG_BUILD_ARG_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_DEBUG_BUILD_ARG_HH 1 + +#include <paludis/args/args_option.hh> +#include <paludis/repository.hh> + +/** \file + * Declarations for the DebugBuildArg class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * The '--debug-build' standard command line argument. + * + * \since 0.26 + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE DebugBuildArg : + public EnumArg + { + public: + ///\name Basic operations + ///\{ + + DebugBuildArg(ArgsGroup * const, const std::string &, char); + ~DebugBuildArg(); + + ///\} + + /** + * Our selected value, as an InstallActionDebugOption. + */ + InstallActionDebugOption option() const; + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/dep_list_args_group.cc b/0.26.0_alpha1/paludis/args/dep_list_args_group.cc new file mode 100644 index 000000000..dd8d92ee5 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/dep_list_args_group.cc @@ -0,0 +1,318 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * Copyright (c) 2007 David Leverton <levertond@googlemail.com> + * + * 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 "dep_list_args_group.hh" + +#include <paludis/util/log.hh> +#include <paludis/util/sequence.hh> + +#include <paludis/args/do_help.hh> +#include <paludis/environment-fwd.hh> +#include <paludis/override_functions.hh> + +using namespace paludis; +using namespace paludis::args; + +namespace +{ + DepListDepsOption + enum_arg_to_dep_list_deps_option(const args::EnumArg & arg) + { + if (arg.argument() == "pre") + return dl_deps_pre; + else if (arg.argument() == "pre-or-post") + return dl_deps_pre_or_post; + else if (arg.argument() == "post") + return dl_deps_post; + else if (arg.argument() == "try-post") + return dl_deps_try_post; + else if (arg.argument() == "discard") + return dl_deps_discard; + else + throw args::DoHelp("bad value for --" + arg.long_name()); + } +} + +DepListArgsGroup::DepListArgsGroup(ArgsHandler * h) : + ArgsGroup(h, "DepList behaviour", + "Modify dependency list generation behaviour. Use with caution."), + + dl_reinstall(this, "dl-reinstall", '\0', "When to reinstall packages", + args::EnumArg::EnumArgOptions + ("never", "Never") + ("always", "Always") + ("if-use-changed", "If USE flags have changed"), + "never"), + dl_reinstall_scm(this, "dl-reinstall-scm", '\0', "When to reinstall scm packages", + args::EnumArg::EnumArgOptions + ("never", "Never") + ("always", "Always") + ("daily", "If they are over a day old") + ("weekly", "If they are over a week old"), + "never"), + dl_reinstall_targets(this, "dl-reinstall-targets", '\0', "Whether to reinstall targets", + args::EnumArg::EnumArgOptions + ("auto", "If the target is a set, never, otherwise always") + ("never", "Never") + ("always", "Always"), + "auto"), + + dl_upgrade(this, "dl-upgrade", '\0', "When to upgrade packages", + args::EnumArg::EnumArgOptions + ("always", "Always") + ("as-needed", "As needed"), + "always"), + dl_new_slots(this, "dl-new-slots", '\0', "When to pull in new slots (works with --dl-upgrade)", + args::EnumArg::EnumArgOptions + ("always", "Always") + ("as-needed", "As needed"), + "always"), + dl_downgrade(this, "dl-downgrade", '\0', "When to downgrade packages", + args::EnumArg::EnumArgOptions + ("as-needed", "As needed") + ("warning", "As needed, but warn when doing so") + ("error", "Downgrades should be treated as errors"), + "as-needed"), + + dl_deps_default(this, "dl-deps-default", '\0', + "Override default behaviour for all dependency classes", + static_cast<DepListDepsOption>(-1)), + + dl_installed_deps_pre(this, "dl-installed-deps-pre", '\0', + "How to handle pre dependencies for installed packages", + dl_deps_discard), + dl_installed_deps_runtime(this, "dl-installed-deps-runtime", '\0', + "How to handle runtime dependencies for installed packages", + dl_deps_try_post), + dl_installed_deps_post(this, "dl-installed-deps-post", '\0', + "How to handle post dependencies for installed packages", + dl_deps_try_post), + + dl_uninstalled_deps_pre(this, "dl-uninstalled-deps-pre", '\0', + "How to handle pre dependencies for uninstalled packages", + dl_deps_pre), + dl_uninstalled_deps_runtime(this, "dl-uninstalled-deps-runtime", '\0', + "How to handle runtime dependencies for uninstalled packages", + dl_deps_pre_or_post), + dl_uninstalled_deps_post(this, "dl-uninstalled-deps-post", '\0', + "How to handle post dependencies for uninstalled packages", + dl_deps_post), + dl_uninstalled_deps_suggested(this, "dl-uninstalled-deps-suggested", '\0', + "How to handle suggested dependencies for uninstalled packages (only with --dl-suggested install)", + dl_deps_post), + + dl_suggested(this, "dl-suggested", '\0', "How to handle suggested dependencies", + args::EnumArg::EnumArgOptions + ("show", "Display, but do not install") + ("install", "Install") + ("discard", "Discard"), + "show"), + dl_circular(this, "dl-circular", '\0', "How to handle circular dependencies", + args::EnumArg::EnumArgOptions + ("error", "Raise an error") + ("discard", "Discard"), + "error"), + dl_blocks(this, "dl-blocks", '\0', "How to handle blocks", + args::EnumArg::EnumArgOptions + ("accumulate", "Accumulate and show in the dependency list") + ("error", "Error straight away") + ("discard", "Discard (dangerous)"), + "error"), + dl_override_masks(this, "dl-override-masks", '\0', + "Zero or more mask kinds that can be overridden as necessary", + args::StringSetArg::StringSetArgOptions + ("tilde-keyword", "Keyword masks where accepting ~ would work") + ("unkeyworded", "Keyword masks where a package is unkeyworded") + ("repository", "Repository masks") + ("profile", "Deprecated synonym for repository") + ("license", "License masks")), + + dl_fall_back(this, "dl-fall-back", '\0', "When to fall back to installed packages", + args::EnumArg::EnumArgOptions + ("as-needed-except-targets", "Where necessary, but not for target packages") + ("as-needed", "Where necessary, including for target packages") + ("never", "Never"), + "as-needed-except-targets") +{ +} + +DepListArgsGroup::~DepListArgsGroup() +{ +} + +void +DepListArgsGroup::populate_dep_list_options(const Environment * env, DepListOptions & options) const +{ + if (dl_reinstall.argument() == "never") + options.reinstall = dl_reinstall_never; + else if (dl_reinstall.argument() == "always") + options.reinstall = dl_reinstall_always; + else if (dl_reinstall.argument() == "if-use-changed") + options.reinstall = dl_reinstall_if_use_changed; + else + throw args::DoHelp("bad value for --dl-reinstall"); + + if (dl_reinstall_scm.argument() == "never") + options.reinstall_scm = dl_reinstall_scm_never; + else if (dl_reinstall_scm.argument() == "always") + options.reinstall_scm = dl_reinstall_scm_always; + else if (dl_reinstall_scm.argument() == "daily") + options.reinstall_scm = dl_reinstall_scm_daily; + else if (dl_reinstall_scm.argument() == "weekly") + options.reinstall_scm = dl_reinstall_scm_weekly; + else + throw args::DoHelp("bad value for --dl-reinstall-scm"); + + if (dl_upgrade.argument() == "as-needed") + options.upgrade = dl_upgrade_as_needed; + else if (dl_upgrade.argument() == "always") + options.upgrade = dl_upgrade_always; + else + throw args::DoHelp("bad value for --dl-upgrade"); + + if (dl_new_slots.argument() == "as-needed") + options.new_slots = dl_new_slots_as_needed; + else if (dl_new_slots.argument() == "always") + options.new_slots = dl_new_slots_always; + else + throw args::DoHelp("bad value for --dl-new-slots"); + + if (dl_downgrade.argument() == "as-needed") + options.downgrade = dl_downgrade_as_needed; + else if (dl_downgrade.argument() == "warning") + options.downgrade = dl_downgrade_warning; + else if (dl_downgrade.argument() == "error") + options.downgrade = dl_downgrade_error; + else + throw args::DoHelp("bad value for --dl-downgrade"); + + if (dl_circular.argument() == "discard") + options.circular = dl_circular_discard; + else if (dl_circular.argument() == "error") + options.circular = dl_circular_error; + else + throw args::DoHelp("bad value for --dl-circular"); + + if (dl_suggested.argument() == "show") + options.suggested = dl_suggested_show; + else if (dl_suggested.argument() == "discard") + options.suggested = dl_suggested_discard; + else if (dl_suggested.argument() == "install") + options.suggested = dl_suggested_install; + else + throw args::DoHelp("bad value for --dl-suggested"); + + if (dl_blocks.argument() == "discard") + options.blocks = dl_blocks_discard; + else if (dl_blocks.argument() == "error") + options.blocks = dl_blocks_error; + else if (dl_blocks.argument() == "accumulate") + options.blocks = dl_blocks_accumulate; + else + throw args::DoHelp("bad value for --dl-blocks"); + + if (dl_override_masks.specified()) + { + for (args::StringSetArg::ConstIterator a(dl_override_masks.begin_args()), + a_end(dl_override_masks.end_args()) ; a != a_end ; ++a) + { + if (! options.override_masks) + options.override_masks.reset(new DepListOverrideMasksFunctions); + + using namespace tr1::placeholders; + + if (*a == "tilde-keyword") + options.override_masks->push_back(tr1::bind(&override_tilde_keywords, env, _1, _2)); + else if (*a == "unkeyworded") + options.override_masks->push_back(tr1::bind(&override_unkeyworded, env, _1, _2)); + else if (*a == "repository") + options.override_masks->push_back(tr1::bind(&override_repository_masks, _2)); + else if (*a == "license") + options.override_masks->push_back(tr1::bind(&override_license, _2)); + else if (*a == "profile") + { + Log::get_instance()->message(ll_warning, lc_no_context, "--dl-override-masks profile is deprecated, use --dl-override-masks repository"); + options.override_masks->push_back(tr1::bind(&override_repository_masks, _2)); + } + else + throw args::DoHelp("bad value for --dl-override-masks"); + } + } + + if (dl_fall_back.argument() == "as-needed-except-targets") + options.fall_back = dl_fall_back_as_needed_except_targets; + else if (dl_fall_back.argument() == "as-needed") + options.fall_back = dl_fall_back_as_needed; + else if (dl_fall_back.argument() == "never") + options.fall_back = dl_fall_back_never; + else + throw args::DoHelp("bad value for --dl-fall-back"); + + if (dl_deps_default.specified()) + { + DepListDepsOption x(dl_deps_default.option()); + options.installed_deps_pre = x; + options.installed_deps_post = x; + options.installed_deps_runtime = x; + options.uninstalled_deps_pre = x; + options.uninstalled_deps_post = x; + options.uninstalled_deps_runtime = x; + options.uninstalled_deps_suggested = x; + } + + options.installed_deps_pre = enum_arg_to_dep_list_deps_option(dl_installed_deps_pre); + options.installed_deps_runtime = enum_arg_to_dep_list_deps_option(dl_installed_deps_runtime); + options.installed_deps_post = enum_arg_to_dep_list_deps_option(dl_installed_deps_post); + + options.uninstalled_deps_pre = enum_arg_to_dep_list_deps_option(dl_uninstalled_deps_pre); + options.uninstalled_deps_runtime = enum_arg_to_dep_list_deps_option(dl_uninstalled_deps_runtime); + options.uninstalled_deps_post = enum_arg_to_dep_list_deps_option(dl_uninstalled_deps_post); + options.uninstalled_deps_suggested = enum_arg_to_dep_list_deps_option(dl_uninstalled_deps_suggested); +} + +void +DepListArgsGroup::populate_install_task(const Environment *, InstallTask & task) const +{ + if (dl_reinstall_targets.specified()) + { + if (dl_reinstall_targets.argument() == "auto") + { + } + else if (dl_reinstall_targets.argument() == "always") + task.override_target_type(dl_target_package); + else if (dl_reinstall_targets.argument() == "never") + task.override_target_type(dl_target_set); + else + throw args::DoHelp("bad value for --dl-reinstall-targets"); + } +} + +std::string +DepListArgsGroup::paludis_command_fragment() const +{ + return ""; +} + +std::string +DepListArgsGroup::resume_command_fragment(const InstallTask &) const +{ + return " --" + dl_deps_default.long_name() + " discard"; +} + diff --git a/0.26.0_alpha1/paludis/args/dep_list_args_group.hh b/0.26.0_alpha1/paludis/args/dep_list_args_group.hh new file mode 100644 index 000000000..fa41c9948 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/dep_list_args_group.hh @@ -0,0 +1,104 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * Copyright (c) 2007 David Leverton <levertond@googlemail.com> + * + * 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_COMMON_ARGS_DEP_LIST_ARGS_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_DEP_LIST_ARGS_HH 1 + +#include <paludis/args/args.hh> +#include <paludis/args/deps_option_arg.hh> +#include <paludis/dep_list.hh> +#include <paludis/install_task.hh> + +namespace paludis +{ + namespace args + { + /** + * The standard dep command line arguments. + * + * \since 0.26 + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE DepListArgsGroup : public ArgsGroup + { + public: + /// Constructor. + DepListArgsGroup(ArgsHandler *); + + /// Destructor + ~DepListArgsGroup(); + + /// \name DepList behaviour arguments + /// { + + paludis::args::EnumArg dl_reinstall; + paludis::args::EnumArg dl_reinstall_scm; + paludis::args::EnumArg dl_reinstall_targets; + paludis::args::EnumArg dl_upgrade; + paludis::args::EnumArg dl_new_slots; + paludis::args::EnumArg dl_downgrade; + + paludis::args::DepsOptionArg dl_deps_default; + + paludis::args::DepsOptionArg dl_installed_deps_pre; + paludis::args::DepsOptionArg dl_installed_deps_runtime; + paludis::args::DepsOptionArg dl_installed_deps_post; + + paludis::args::DepsOptionArg dl_uninstalled_deps_pre; + paludis::args::DepsOptionArg dl_uninstalled_deps_runtime; + paludis::args::DepsOptionArg dl_uninstalled_deps_post; + paludis::args::DepsOptionArg dl_uninstalled_deps_suggested; + + paludis::args::EnumArg dl_suggested; + paludis::args::EnumArg dl_circular; + paludis::args::EnumArg dl_blocks; + paludis::args::StringSetArg dl_override_masks; + + paludis::args::EnumArg dl_fall_back; + + /// } + + /** + * Populate a DepListOptions from our values. + */ + void populate_dep_list_options(const paludis::Environment *, DepListOptions &) const; + + /** + * Populate an InstallTask from our values. + */ + void populate_install_task(const paludis::Environment *, InstallTask &) const; + + /** + * Fetch a fragment for Environment::paludis_command for our + * values. + */ + std::string paludis_command_fragment() const; + + /** + * Fetch a fragment for a resume command for our values. + */ + std::string resume_command_fragment(const InstallTask &) const; + }; + } +} + +#endif + diff --git a/0.26.0_alpha1/paludis/args/deps_option_arg.cc b/0.26.0_alpha1/paludis/args/deps_option_arg.cc new file mode 100644 index 000000000..538ebcc59 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/deps_option_arg.cc @@ -0,0 +1,89 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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 "deps_option_arg.hh" +#include "do_help.hh" +#include <paludis/util/stringify.hh> + +using namespace paludis; +using namespace paludis::args; + +namespace +{ + std::string def_to_string(const DepListDepsOption d) + { + if (-1 == d) + return "none"; + + switch (d) + { + case dl_deps_discard: + return "discard"; + case dl_deps_pre: + return "pre"; + case dl_deps_pre_or_post: + return "pre-or-post"; + case dl_deps_post: + return "post"; + case dl_deps_try_post: + return "try-post"; + case last_dl_deps: + ; + }; + + throw InternalError(PALUDIS_HERE, "Unexpected DepListDepsOption value"); + } +} + +DepsOptionArg::DepsOptionArg(ArgsGroup * const grp, const std::string & ln, + char sh, const std::string & desc, const DepListDepsOption def) : + EnumArg(grp, ln, sh, desc, + EnumArgOptions + ("pre", "As pre dependencies") + ("pre-or-post", "As pre dependencies, or post dependencies where needed") + ("post", "As post dependencies") + ("try-post", "As post dependencies, with no error for failures") + ("discard", "Discard"), + def_to_string(def)) +{ +} + +DepsOptionArg::~DepsOptionArg() +{ +} + +DepListDepsOption +DepsOptionArg::option() const +{ + if ("pre" == argument()) + return dl_deps_pre; + if ("pre-or-post" == argument()) + return dl_deps_pre_or_post; + if ("post" == argument()) + return dl_deps_post; + if ("try-post" == argument()) + return dl_deps_try_post; + if ("discard" == argument()) + return dl_deps_discard; + + throw DoHelp("Bad value for --" + long_name()); +} + + + diff --git a/0.26.0_alpha1/paludis/args/deps_option_arg.hh b/0.26.0_alpha1/paludis/args/deps_option_arg.hh new file mode 100644 index 000000000..560b8e35c --- /dev/null +++ b/0.26.0_alpha1/paludis/args/deps_option_arg.hh @@ -0,0 +1,69 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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_COMMON_ARGS_DEPS_OPTION_ARG_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_DEPS_OPTION_ARG_HH 1 + +#include <paludis/args/args_option.hh> +#include <paludis/dep_list.hh> + +/** \file + * Declarations for the DepsOptionArg class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * A '--dl-deps-' standard command line argument. + * + * \since 0.26 + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE DepsOptionArg : + public EnumArg + { + public: + ///\name Basic operations + ///\{ + + DepsOptionArg(ArgsGroup * const, const std::string &, char, + const std::string &, const DepListDepsOption); + ~DepsOptionArg(); + + ///\} + + /** + * Our selected value, as a DepListDepsOption. + */ + DepListDepsOption option() const; + }; + + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/do_help.hh b/0.26.0_alpha1/paludis/args/do_help.hh new file mode 100644 index 000000000..80f9771dc --- /dev/null +++ b/0.26.0_alpha1/paludis/args/do_help.hh @@ -0,0 +1,63 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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_COMMON_ARGS_DO_HELP_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_DO_HELP_HH 1 + +/** \file + * Declarations for the DoHelp class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * Convenience struct for --help handling. + * + * \ingroup g_args + */ + struct PALUDIS_VISIBLE DoHelp + { + /** + * Our message, if one is necessary. + */ + const std::string message; + + ///\name Basic operations + ///\{ + + DoHelp(const std::string & m = "") : + message(m) + { + } + + ///\} + }; + } +} + + +#endif diff --git a/0.26.0_alpha1/paludis/args/install_args_group.cc b/0.26.0_alpha1/paludis/args/install_args_group.cc new file mode 100644 index 000000000..86bac5634 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/install_args_group.cc @@ -0,0 +1,221 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * Copyright (c) 2007 David Leverton <levertond@googlemail.com> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "install_args_group.hh" + +#include <paludis/environment-fwd.hh> +#include <paludis/args/do_help.hh> + +using namespace paludis; +using namespace paludis::args; + +InstallArgsGroup::InstallArgsGroup(ArgsHandler * h, const std::string & our_name, + const std::string & our_description) : + ArgsGroup(h, our_name, our_description), + + a_pretend(this, "pretend", 'p', "Pretend only"), + a_destinations(this, "destinations", 'd', "Use specified destinations instead of defaults"), + a_preserve_world(this, "preserve-world", '1', "Don't modify the world file"), + a_add_to_world_spec(this, "add-to-world-spec", '\0', + "Use this spec, rather than all targets, for updating world (for resume commands)"), + a_no_config_protection(this, "no-config-protection", '\0', "Disable config file protection (dangerous)"), + a_debug_build(this, "debug-build", '\0'), + a_checks(this, "checks", '\0'), + a_fetch(this, "fetch", 'f', "Only fetch sources; don't install anything"), + a_no_safe_resume(this, "no-safe-resume", '\0', "Do not allow interrupted downloads to be resumed"), + a_show_reasons(this, "show-reasons", '\0', "Show why packages are being (un)installed", + args::EnumArg::EnumArgOptions + ("none", "Don't show any information") + ("summary", "Show a summary") + ("full", "Show full output (can be very verbose)"), + "none"), + a_show_use_descriptions(this, "show-use-descriptions", '\0', "Show descriptions of USE flags", + args::EnumArg::EnumArgOptions + ("none", "Don't show any descriptions") + ("new", "Show for new use flags") + ("changed", "Show for new and changed flags") + ("all", "Show for all flags"), + "none"), + a_continue_on_faillure(this, "continue-on-failure", '\0', "Whether to continue after a fetch or install error", + args::EnumArg::EnumArgOptions + ("if-fetch-only", "If fetching only") + ("never", "Never") + ("if-satisfied", "If remaining packages' dependencies are satisfied") + ("always", "Always (UNSAFE)"), + "if-fetch-only") +{ +} + +InstallArgsGroup::~InstallArgsGroup() +{ +} + +void +InstallArgsGroup::populate_dep_list_options(const Environment *, DepListOptions & options) const +{ + options.dependency_tags = a_show_reasons.argument() == "summary" || a_show_reasons.argument() == "full"; +} + +tr1::shared_ptr<const DestinationsSet> +InstallArgsGroup::destinations(Environment * env) const +{ + if (a_destinations.specified()) + { + Context local_context("When building destinations collection:"); + + tr1::shared_ptr<DestinationsSet> d(new DestinationsSet); + for (args::StringSetArg::ConstIterator i(a_destinations.begin_args()), + i_end(a_destinations.end_args()) ; + i != i_end ; ++i) + { + tr1::shared_ptr<Repository> repo(env->package_database()->fetch_repository( + RepositoryName(*i))); + if (repo->destination_interface) + d->insert(repo); + else + throw args::DoHelp("--destinations argument '" + *i + "' does not provide a destinations interface"); + } + + return d; + } + else + return env->default_destinations(); +} + +void +InstallArgsGroup::populate_install_task(const Environment *, InstallTask & task) const +{ + task.set_no_config_protect(a_no_config_protection.specified()); + task.set_fetch_only(a_fetch.specified()); + task.set_pretend(a_pretend.specified()); + task.set_preserve_world(a_preserve_world.specified()); + task.set_safe_resume(! a_no_safe_resume.specified()); + + if (a_add_to_world_spec.specified()) + task.set_add_to_world_spec(a_add_to_world_spec.argument()); + + task.set_debug_mode(a_debug_build.option()); + task.set_checks_mode(a_checks.option()); + + if (a_continue_on_faillure.argument() == "if-fetch-only") + task.set_continue_on_failure(itcof_if_fetch_only); + else if (a_continue_on_faillure.argument() == "never") + task.set_continue_on_failure(itcof_never); + else if (a_continue_on_faillure.argument() == "if-satisfied") + task.set_continue_on_failure(itcof_if_satisfied); + else if (a_continue_on_faillure.argument() == "always") + task.set_continue_on_failure(itcof_always); + else + throw args::DoHelp("bad value for --continue-on-failure"); +} + +bool +InstallArgsGroup::want_full_install_reasons() const +{ + return "full" == a_show_reasons.argument(); +} + +bool +InstallArgsGroup::want_tags_summary() const +{ + return a_pretend.specified(); +} + +bool +InstallArgsGroup::want_install_reasons() const +{ + if (! a_pretend.specified()) + return false; + + return "full" == a_show_reasons.argument() || "summary" == a_show_reasons.argument(); +} + +bool +InstallArgsGroup::want_unchanged_use_flags() const +{ + return "none" != a_show_use_descriptions.argument() && + "new" != a_show_use_descriptions.argument() && + "changed" != a_show_use_descriptions.argument(); +} + +bool +InstallArgsGroup::want_changed_use_flags() const +{ + return "none" != a_show_use_descriptions.argument() && "new" != a_show_use_descriptions.argument(); +} + +bool +InstallArgsGroup::want_new_use_flags() const +{ + return "none" != a_show_use_descriptions.argument(); +} + +bool +InstallArgsGroup::want_use_summary() const +{ + return "none" != a_show_use_descriptions.argument(); +} + +std::string +InstallArgsGroup::paludis_command_fragment() const +{ + std::string paludis_command; + + if (a_no_config_protection.specified()) + paludis_command.append(" --" + a_no_config_protection.long_name()); + + if (a_preserve_world.specified()) + paludis_command.append(" --" + a_preserve_world.long_name()); + + if (a_debug_build.specified()) + paludis_command.append(" --" + a_debug_build.long_name() + " " + a_debug_build.argument()); + + if (a_no_safe_resume.specified()) + paludis_command.append(" --" + a_no_safe_resume.long_name()); + + return paludis_command; +} + +std::string +InstallArgsGroup::resume_command_fragment(const InstallTask & task) const +{ + std::string resume_command; + + if (a_add_to_world_spec.specified()) + resume_command = resume_command + " --" + a_add_to_world_spec.long_name() + + " '" + a_add_to_world_spec.argument() + "'"; + else if (! a_preserve_world.specified()) + { + if (task.had_set_targets()) + resume_command = resume_command + " --" + a_add_to_world_spec.long_name() + + " '( )'"; + else + resume_command = resume_command + " --" + a_add_to_world_spec.long_name() + + " '( " + join(task.begin_targets(), task.end_targets(), " ") + " )'"; + } + + if (a_destinations.specified()) + for (args::StringSetArg::ConstIterator i(a_destinations.begin_args()), + i_end(a_destinations.end_args()) ; i != i_end ; ++i) + resume_command = resume_command + " --" + a_destinations.long_name() + " '" + *i + "'"; + + return resume_command; +} + diff --git a/0.26.0_alpha1/paludis/args/install_args_group.hh b/0.26.0_alpha1/paludis/args/install_args_group.hh new file mode 100644 index 000000000..3a6ce792b --- /dev/null +++ b/0.26.0_alpha1/paludis/args/install_args_group.hh @@ -0,0 +1,145 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * Copyright (c) 2007 David Leverton <levertond@googlemail.com> + * + * 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_COMMON_ARGS_INSTALL_ARGS_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_INSTALL_ARGS_HH 1 + +#include <paludis/util/set.hh> + +#include <paludis/args/args.hh> +#include <paludis/args/checks_arg.hh> +#include <paludis/args/debug_build_arg.hh> +#include <paludis/dep_list-fwd.hh> +#include <paludis/install_task.hh> + +/** \file + * Declarations for the InstallArgsGroup class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * Standard install arguments. + * + * \ingroup g_args + * \since 0.26 + * \nosubgrouping + */ + class PALUDIS_VISIBLE InstallArgsGroup : public ArgsGroup + { + public: + /// Constructor. + InstallArgsGroup(ArgsHandler *, const std::string &, const std::string &); + + /// Destructor + ~InstallArgsGroup(); + + /// \name (Un)Install arguments + /// { + + /// --pretend + paludis::args::SwitchArg a_pretend; + + /// --destinations + paludis::args::StringSetArg a_destinations; + + /// --preserve-world + paludis::args::SwitchArg a_preserve_world; + + /// --add-to-world-spec + paludis::args::StringArg a_add_to_world_spec; + + /// --no-config-protection + paludis::args::SwitchArg a_no_config_protection; + + /// --debug-build + paludis::args::DebugBuildArg a_debug_build; + + /// --checks + paludis::args::ChecksArg a_checks; + + /// --fetch + paludis::args::SwitchArg a_fetch; + + /// --no-safe-resume + paludis::args::SwitchArg a_no_safe_resume; + + /// --show-reasons + paludis::args::EnumArg a_show_reasons; + + /// --show-use-descriptions + paludis::args::EnumArg a_show_use_descriptions; + + /// --continue-on-failure + paludis::args::EnumArg a_continue_on_faillure; + + /// } + + /** + * Populate a DepListOptions from our values. + */ + void populate_dep_list_options(const Environment *, DepListOptions &) const; + + /** + * Fetch our specified destinations set. + */ + tr1::shared_ptr<const DestinationsSet> destinations(Environment *) const; + + /** + * Populate an InstallTask from our values. + */ + void populate_install_task(const Environment *, InstallTask &) const; + + ///\name Assorted options + ///\{ + + bool want_full_install_reasons() const; + bool want_install_reasons() const; + bool want_tags_summary() const; + + bool want_use_summary() const; + bool want_unchanged_use_flags() const; + bool want_changed_use_flags() const; + bool want_new_use_flags() const; + + ///\} + + /** + * Create a fragment for Environment::paludis_command. + */ + std::string paludis_command_fragment() const; + + /** + * Create a fragment for a resume command. + */ + std::string resume_command_fragment(const InstallTask &) const; + }; + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/log_level_arg.cc b/0.26.0_alpha1/paludis/args/log_level_arg.cc new file mode 100644 index 000000000..c42111e35 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/log_level_arg.cc @@ -0,0 +1,57 @@ +/* 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 "log_level_arg.hh" +#include "do_help.hh" + +using namespace paludis; +using namespace paludis::args; + +LogLevelArg::LogLevelArg(ArgsGroup * const grp, const std::string & ln, + char sh) : + EnumArg(grp, ln, sh, "Specify the log level", + EnumArgOptions + ("debug", "Show debug output (noisy)") + ("qa", "Show QA messages and warnings only") + ("warning", "Show warnings only") + ("silent", "Suppress all log messages (UNSAFE)"), + "qa") +{ +} + +LogLevelArg::~LogLevelArg() +{ +} + +LogLevel +LogLevelArg::option() const +{ + if ("debug" == argument()) + return ll_debug; + if ("qa" == argument()) + return ll_qa; + if ("warning" == argument()) + return ll_warning; + if ("silent" == argument()) + return ll_silent; + + throw DoHelp("Bad value for --" + long_name()); +} + + diff --git a/0.26.0_alpha1/paludis/args/log_level_arg.hh b/0.26.0_alpha1/paludis/args/log_level_arg.hh new file mode 100644 index 000000000..97725481a --- /dev/null +++ b/0.26.0_alpha1/paludis/args/log_level_arg.hh @@ -0,0 +1,68 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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_COMMON_ARGS_LOG_LEVEL_ARG_HH +#define PALUDIS_GUARD_SRC_COMMON_ARGS_LOG_LEVEL_ARG_HH 1 + +#include <paludis/args/args_option.hh> +#include <paludis/util/log.hh> + +/** \file + * Declarations for the LogLevelArg class. + * + * \ingroup g_args + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + namespace args + { + /** + * The '--log-level' standard command line argument. + * + * \since 0.26 + * \ingroup g_args + * \nosubgrouping + */ + class PALUDIS_VISIBLE LogLevelArg : + public EnumArg + { + public: + ///\name Basic operations + ///\{ + + LogLevelArg(ArgsGroup * const, const std::string &, char); + ~LogLevelArg(); + + ///\} + + /** + * Our selected value, as a LogLevel. + */ + LogLevel option() const; + }; + + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/args/man.cc b/0.26.0_alpha1/paludis/args/man.cc new file mode 100644 index 000000000..5c140b952 --- /dev/null +++ b/0.26.0_alpha1/paludis/args/man.cc @@ -0,0 +1,409 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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 "man.hh" +#include <paludis/util/visitor-impl.hh> +#include <ostream> +#include <sstream> + +using namespace paludis; +using namespace paludis::args; +using std::endl; + +namespace +{ + struct ExtraText : + ConstVisitor<ArgsVisitorTypes> + { + DocWriter & _dw; + + ExtraText(DocWriter & dw) : + _dw(dw) + { + } + + void visit(const ArgsOption &) + { + } + + void visit(const StringArg &) + { + } + + void visit(const AliasArg &) + { + } + + void visit(const SwitchArg &) + { + } + + void visit(const IntegerArg &) + { + } + + void visit(const EnumArg & e) + { + if (e.begin_allowed_args() == e.end_allowed_args()) + return; + + _dw.start_extra_arg(); + + for (EnumArg::AllowedArgConstIterator a(e.begin_allowed_args()), a_end(e.end_allowed_args()) ; + a != a_end ; ++a) + { + _dw.extra_arg_enum(a->first, a->second, e.default_arg()); + } + + _dw.end_extra_arg(); + } + + void visit(const StringSetArg & e) + { + if (e.begin_allowed_args() == e.end_allowed_args()) + return; + + _dw.start_extra_arg(); + + for (EnumArg::AllowedArgConstIterator a(e.begin_allowed_args()), a_end(e.end_allowed_args()) ; + a != a_end ; ++a) + { + _dw.extra_arg_string_set(a->first, a->second); + } + + _dw.end_extra_arg(); + } + }; +} + + +void +paludis::args::generate_doc(DocWriter & dw, const ArgsHandler * const h) +{ + dw.heading(h->app_name(), h->man_section(), h->app_synopsis()); + + for (ArgsHandler::UsageLineConstIterator u(h->begin_usage_lines()), + u_end(h->end_usage_lines()) ; u != u_end ; ++u) + { + dw.usage_line(h->app_name(), *u); + } + + dw.start_description(h->app_description()); + + for (ArgsHandler::ArgsGroupsConstIterator a(h->begin_args_groups()), + a_end(h->end_args_groups()) ; a != a_end ; ++a) + { + dw.start_arg_group((*a)->name(), (*a)->description()); + + for (paludis::args::ArgsGroup::ConstIterator b((*a)->begin()), b_end((*a)->end()) ; + b != b_end ; ++b) + { + dw.arg_group_item((*b)->short_name(), (*b)->long_name(), (*b)->description()); + + ExtraText t(dw); + (*b)->accept(t); + + dw.end_arg_group(); + } + + dw.end_description(); + } + + if (h->begin_environment_lines() != h->end_environment_lines()) + { + dw.start_environment(); + + for (ArgsHandler::EnvironmentLineConstIterator a(h->begin_environment_lines()), + a_end(h->end_environment_lines()) ; a != a_end ; ++a) + { + dw.environment_line(a->first, a->second); + } + + dw.end_environment(); + } +} + +DocWriter::~DocWriter() +{ +} + +HtmlWriter::HtmlWriter(std::ostream & os) : + _os(os) +{ +} + +HtmlWriter::~HtmlWriter() +{ +} + +void +HtmlWriter::heading(const std::string & name, const std::string & section_, const std::string & synopsis) +{ + _os << "<h1>" << name << "(" << section_ << ")" << "</h1>" << endl; + _os << "<h2>Name</h2>" << endl; + _os << "<p>" << name << " - " << synopsis << "</p>" << endl; + _os << "<h2>Synopsis</h2>" << endl; +} + +void +HtmlWriter::usage_line(const std::string & name, const std::string & line) +{ + _os << "<p>" << name << " " << line << "</p>" << endl; +} + +void +HtmlWriter::start_description(const std::string & description) +{ + _os << "<h2>Description</h2>" << endl; + _os << "<p>" << description << "</p>" << endl; + _os << "<h2>Options</h2>" << endl; +} + +void +HtmlWriter::start_arg_group(const std::string & name, const std::string & description) +{ + _os << "<h3>" << name << "</h3>" << endl; + _os << "<p>" << description << "</p>" << endl; + _os << "<dl>"; +} + +void +HtmlWriter::arg_group_item(const char & short_name, const std::string & long_name, + const std::string & description) +{ + _os << "<dt>"; + if (short_name) + _os << "-" << short_name << ", "; + _os << "--" << long_name << "</dt>" << endl; + _os << "<dd>" << description << endl; +} + +void +HtmlWriter::start_extra_arg() +{ + _os << "<dl>" << endl; +} + +void +HtmlWriter::extra_arg_enum(const std::string & first, const std::string & second, const std::string & default_arg) +{ + std::string default_string; + if (first == default_arg) + default_string = " (default)"; + + _os << "<dt>" << first << "</dt>" << endl; + _os << "<dd>" << second << default_string << "</dd>" << endl; +} + +void +HtmlWriter::extra_arg_string_set(const std::string & first, const std::string & second) +{ + _os << "<dt>" << first << "</dt>" << endl; + _os << "<dd>" << second << "</dd>" << endl; +} + +void +HtmlWriter::end_extra_arg() +{ + _os << "</dl>" << endl; +} + +void +HtmlWriter::end_arg_group() +{ + _os << "</dd>" << endl; +} + +void +HtmlWriter::end_description() +{ + _os << "</dl>" << endl; +} + +void +HtmlWriter::start_environment() +{ + _os << "<h2>Environment</h2>" << endl; + _os << "<dl>" << endl; +} + +void +HtmlWriter::environment_line(const std::string & first, const std::string & second) +{ + _os << "<dt>" << first << "</dt>" << endl; + _os << "<dd>" << second << "</dd>" << endl; +} + +void +HtmlWriter::end_environment() +{ + _os << "</dl>" << endl; +} + +void +HtmlWriter::section(const std::string & title) +{ + _os << "<h2>" << title << "</h2>" << endl; +} + +void +HtmlWriter::subsection(const std::string & title) +{ + _os << "<h3>" << title << "</h3>" << endl; +} + +void +HtmlWriter::paragraph(const std::string & text) +{ + _os << "<p>" << text << "</p>" << endl; +} + + +ManWriter::ManWriter(std::ostream & os) : + _os(os) +{ +} + +ManWriter::~ManWriter() +{ +} + +void +ManWriter::heading(const std::string & name, const std::string & section_, const std::string & synopsis) +{ + _os << ".TH \"" << name << "\" " << section_ << endl; + _os << ".SH NAME" << endl; + _os << name << " \\- " << synopsis << endl; + _os << ".SH SYNOPSIS" << endl; +} + +void +ManWriter::usage_line(const std::string & name, const std::string & line) +{ + _os << ".B " << name << " " << line << endl << endl; +} + +void +ManWriter::start_description(const std::string & description) +{ + _os << ".SH DESCRIPTION" << endl; + _os << description << endl; + _os << ".SH OPTIONS" << endl; +} + +void +ManWriter::start_arg_group(const std::string & name, const std::string & description) +{ + _os << ".SS \"" << name << "\"" << endl; + _os << description << endl; +} + +void +ManWriter::arg_group_item(const char & short_name, const std::string & long_name, + const std::string & description) +{ + _os << ".TP" << endl; + _os << ".B \""; + if (short_name) + _os << "\\-" << short_name << " , "; + _os << "\\-\\-" << long_name << "\"" << endl; + _os << description << endl; +} + +void +ManWriter::start_extra_arg() +{ +} + +void +ManWriter::extra_arg_enum(const std::string & first, const std::string & second, const std::string & default_arg) +{ + std::string default_string; + if (first == default_arg) + default_string = " (default)"; + + _os << ".RS" << endl; + _os << ".TP" << endl; + _os << ".B \"" << first << "\"" << endl; + _os << second << default_string << endl; + _os << ".RE" << endl; +} + +void +ManWriter::extra_arg_string_set(const std::string & first, const std::string & second) +{ + _os << ".RS" << endl; + _os << ".TP" << endl; + _os << ".B \"" << first << "\"" << endl; + _os << second << endl; + _os << ".RE" << endl; +} + +void +ManWriter::end_extra_arg() +{ +} + +void +ManWriter::end_arg_group() +{ +} + +void +ManWriter::end_description() +{ +} + +void +ManWriter::start_environment() +{ + _os << ".SH ENVIRONMENT" << endl; +} + +void +ManWriter::environment_line(const std::string & first, const std::string & second) +{ + _os << ".TP" << endl; + _os << ".B \"" << first << "\"" << endl; + _os << second << endl; +} + +void +ManWriter::end_environment() +{ +} + +void +ManWriter::section(const std::string & title) +{ + _os << ".SH " << title << endl; +} + +void +ManWriter::subsection(const std::string & title) +{ + _os << ".SS \"" << title << "\"" << endl; +} + +void +ManWriter::paragraph(const std::string & text) +{ + _os << text << endl; +} + diff --git a/0.26.0_alpha1/paludis/args/man.hh b/0.26.0_alpha1/paludis/args/man.hh new file mode 100644 index 000000000..94767770d --- /dev/null +++ b/0.26.0_alpha1/paludis/args/man.hh @@ -0,0 +1,180 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_ARGS_MAN_HH +#define PALUDIS_GUARD_PALUDIS_ARGS_MAN_HH 1 + +#include <paludis/args/args.hh> +#include <iosfwd> + +namespace paludis +{ + namespace args + { + class DocWriter; + + /** + * Write docs to an ostream. + * + * \ingroup grplibpaludisargs + */ + void generate_doc(DocWriter & dw, const ArgsHandler * const h) PALUDIS_VISIBLE; + + /** + * Write docs from args classes in a particular format. + * + * \ingroup grplibpaludisargs + * \nosubgrouping + */ + class PALUDIS_VISIBLE DocWriter + { + public: + ///\name Basic operations + ///\{ + + virtual ~DocWriter() = 0; + + ///\} + + ///\name Output routines + ///\{ + + virtual void heading(const std::string & name, const std::string & section, + const std::string & synopsis) = 0; + virtual void usage_line(const std::string & name, const std::string & line) = 0; + + virtual void start_description(const std::string & description) = 0; + virtual void start_arg_group(const std::string & name, const std::string & description) = 0; + virtual void arg_group_item(const char & short_name, const std::string & long_name, + const std::string & description) = 0; + virtual void start_extra_arg() = 0; + virtual void extra_arg_enum(const std::string & first, const std::string & second, + const std::string & default_arg) = 0; + virtual void extra_arg_string_set(const std::string & first, const std::string & second) = 0; + virtual void end_extra_arg() = 0; + virtual void end_arg_group() = 0; + virtual void end_description() = 0; + + virtual void start_environment() = 0; + virtual void environment_line(const std::string & first, const std::string & second) = 0; + virtual void end_environment() = 0; + + virtual void section(const std::string & title) = 0; + virtual void subsection(const std::string & title) = 0; + virtual void paragraph(const std::string & text) = 0; + + ///\} + }; + + /** + * Create HTML documentation from args classes. + * + * \ingroup grplibpaludisargs + * \nosubgrouping + */ + class PALUDIS_VISIBLE HtmlWriter : + public DocWriter + { + private: + std::ostream & _os; + + public: + ///\name Basic operations + ///\{ + + HtmlWriter(std::ostream & os); + ~HtmlWriter(); + + ///\} + + void heading(const std::string & name, const std::string & section, + const std::string & synopis); + void usage_line(const std::string & name, const std::string & line); + + void start_description(const std::string & description); + void start_arg_group(const std::string & name, const std::string & description); + void arg_group_item(const char & short_name, const std::string & long_name, + const std::string & description); + void start_extra_arg(); + void extra_arg_enum(const std::string & first, const std::string & second, + const std::string & default_arg); + void extra_arg_string_set(const std::string & first, const std::string & second); + void end_extra_arg(); + void end_arg_group(); + void end_description(); + + void start_environment(); + void environment_line(const std::string & first, const std::string & second); + void end_environment(); + + void section(const std::string & title); + void subsection(const std::string & title); + void paragraph(const std::string & text); + }; + + /** + * Create man documentation from args classes. + * + * \ingroup grplibpaludisargs + * \nosubgrouping + */ + class PALUDIS_VISIBLE ManWriter : + public DocWriter + { + private: + std::ostream & _os; + + public: + ///\name Basic operations + ///\{ + + ManWriter(std::ostream & os); + ~ManWriter(); + + ///\} + + void heading(const std::string & name, const std::string & section, + const std::string & synopis); + void usage_line(const std::string & name, const std::string & line); + + void start_description(const std::string & description); + void start_arg_group(const std::string & name, const std::string & description); + void arg_group_item(const char & short_name, const std::string & long_name, + const std::string & description); + void start_extra_arg(); + void extra_arg_enum(const std::string & first, const std::string & second, + const std::string & default_arg); + void extra_arg_string_set(const std::string & first, const std::string & second); + void end_extra_arg(); + void end_arg_group(); + void end_description(); + + void start_environment(); + void environment_line(const std::string & first, const std::string & second); + void end_environment(); + + void section(const std::string & title); + void subsection(const std::string & title); + void paragraph(const std::string & text); + }; + + } +} + +#endif diff --git a/0.26.0_alpha1/paludis/condition_tracker.cc b/0.26.0_alpha1/paludis/condition_tracker.cc new file mode 100644 index 000000000..b915198f7 --- /dev/null +++ b/0.26.0_alpha1/paludis/condition_tracker.cc @@ -0,0 +1,146 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 David Leverton <levertond@googlemail.com> + * + * 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 <paludis/condition_tracker.hh> +#include <paludis/util/stringify.hh> +#include <paludis/util/visitor-impl.hh> +#include <paludis/dep_spec.hh> +#include <paludis/dep_label.hh> +#include <libwrapiter/libwrapiter_forward_iterator.hh> +#include <libwrapiter/libwrapiter_output_iterator.hh> + +using namespace paludis; +using namespace tr1::placeholders; + +ConditionTracker::ConditionTracker( + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > conditions) : + base(new ConstTreeSequence<DependencySpecTree, AllDepSpec>( + tr1::shared_ptr<AllDepSpec>(new AllDepSpec))), + adder(tr1::bind(&ConstTreeSequence<DependencySpecTree, AllDepSpec>::add, base, _1)) +{ + conditions->accept(*this); +} + +ConditionTracker::~ConditionTracker() +{ +} + +template <typename T_> +tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > +ConditionTracker::do_add_sequence(const T_ & node) +{ + adder(tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, T_> >( + new ConstTreeSequence<DependencySpecTree, T_>( + tr1::static_pointer_cast<T_>(node.clone())))); + return base; +} + +template <typename T_> +tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > +ConditionTracker::do_add_leaf(const T_ & node) +{ + adder(tr1::shared_ptr<TreeLeaf<DependencySpecTree, T_> >( + new TreeLeaf<DependencySpecTree, T_>( + tr1::static_pointer_cast<T_>(node.clone())))); + return base; +} + +tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > +ConditionTracker::add_condition(const AnyDepSpec & any) +{ + return do_add_sequence(any); +} + +tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > +ConditionTracker::add_condition(const UseDepSpec & use) +{ + return do_add_sequence(use); +} + +tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > +ConditionTracker::add_condition(const PackageDepSpec & pkg) +{ + return do_add_leaf(pkg); +} + +tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > +ConditionTracker::add_condition(const BlockDepSpec & block) +{ + return do_add_leaf(block); +} + +template <typename T_> +void +ConditionTracker::do_visit_sequence(const T_ & node, + DependencySpecTree::ConstSequenceIterator begin, + DependencySpecTree::ConstSequenceIterator end) +{ + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, T_> > a( + new ConstTreeSequence<DependencySpecTree, T_>( + tr1::static_pointer_cast<T_>(node.clone()))); + adder(a); + adder = tr1::bind(&ConstTreeSequence<DependencySpecTree, T_>::add, a, _1); + if (begin != end) + { + begin->accept(*this); + if (++begin != end) + throw InternalError(PALUDIS_HERE, "ConditionTracker saw a sequence with more than one element"); + } +} + +void +ConditionTracker::visit_sequence(const AnyDepSpec & node, + DependencySpecTree::ConstSequenceIterator begin, + DependencySpecTree::ConstSequenceIterator end) +{ + do_visit_sequence(node, begin, end); +} + +void +ConditionTracker::visit_sequence(const UseDepSpec & node, + DependencySpecTree::ConstSequenceIterator begin, + DependencySpecTree::ConstSequenceIterator end) +{ + do_visit_sequence(node, begin, end); +} + +void +ConditionTracker::visit_leaf(const PackageDepSpec &) +{ + throw InternalError(PALUDIS_HERE, "ConditionTracker saw a PackageDepSpec"); +} + +void +ConditionTracker::visit_leaf(const BlockDepSpec &) +{ + throw InternalError(PALUDIS_HERE, "ConditionTracker saw a BlockDepSpec"); +} + +void +ConditionTracker::visit_leaf(const DependencyLabelsDepSpec &) +{ + throw InternalError(PALUDIS_HERE, "ConditionTracker saw a DependencyLabelsDepSpec"); +} + +void +ConditionTracker::visit_leaf(const NamedSetDepSpec &) +{ + throw InternalError(PALUDIS_HERE, "ConditionTracker saw a NamedSetDepSpec"); +} + diff --git a/0.26.0_alpha1/paludis/condition_tracker.hh b/0.26.0_alpha1/paludis/condition_tracker.hh new file mode 100644 index 000000000..8ff43cb5c --- /dev/null +++ b/0.26.0_alpha1/paludis/condition_tracker.hh @@ -0,0 +1,103 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 David Leverton <levertond@googlemail.com> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_CONDITION_TRACKER_HH +#define PALUDIS_GUARD_PALUDIS_CONDITION_TRACKER_HH 1 + +#include <paludis/util/tr1_memory.hh> +#include <paludis/util/tr1_functional.hh> +#include <paludis/util/visitor.hh> +#include <paludis/dep_tree.hh> +#include <paludis/dep_spec-fwd.hh> + +/** \file + * Declarations for ConditionTracker, which is used internally by DepList. + * + * \ingroup g_dep_list + * + * \section Examples + * + * - None at this time. + */ + +namespace paludis +{ + /** + * ConditionTracker is used by DepList to track the conditions under which a + * dependency was pulled in. + * + * \ingroup g_dep_list + * \nosubgrouping + */ + class ConditionTracker : + public ConstVisitor<DependencySpecTree>, + public ConstVisitor<DependencySpecTree>::VisitConstSequence<ConditionTracker, AllDepSpec> + { + private: + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > base; + tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<DependencySpecTree> >)> adder; + + template <typename T_> + void do_visit_sequence(const T_ &, + DependencySpecTree::ConstSequenceIterator, + DependencySpecTree::ConstSequenceIterator); + + template <typename T_> + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > do_add_sequence(const T_ &); + template <typename T_> + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > do_add_leaf(const T_ &); + + public: + ///\name Basic operations + ///\{ + + ConditionTracker(tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> >); + + virtual ~ConditionTracker(); + + ///\} + + ///\name Add a condition + ///\{ + + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > add_condition(const AnyDepSpec &); + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > add_condition(const UseDepSpec &); + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > add_condition(const PackageDepSpec &); + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > add_condition(const BlockDepSpec &); + + ///\} + + ///\name Visit methods + ///\{ + + using ConstVisitor<DependencySpecTree>::VisitConstSequence<ConditionTracker, AllDepSpec>::visit_sequence; + + void visit_sequence(const AnyDepSpec &, DependencySpecTree::ConstSequenceIterator, DependencySpecTree::ConstSequenceIterator); + void visit_sequence(const UseDepSpec &, DependencySpecTree::ConstSequenceIterator, DependencySpecTree::ConstSequenceIterator); + + void visit_leaf(const PackageDepSpec &) PALUDIS_ATTRIBUTE((noreturn)); + void visit_leaf(const BlockDepSpec &) PALUDIS_ATTRIBUTE((noreturn)); + void visit_leaf(const DependencyLabelsDepSpec &) PALUDIS_ATTRIBUTE((noreturn)); + void visit_leaf(const NamedSetDepSpec &) PALUDIS_ATTRIBUTE((noreturn)); + + ///\} + }; +} + +#endif diff --git a/0.26.0_alpha1/paludis/contents-fwd.hh b/0.26.0_alpha1/paludis/contents-fwd.hh new file mode 100644 index 000000000..3518bb36d --- /dev/null +++ b/0.26.0_alpha1/paludis/contents-fwd.hh @@ -0,0 +1,61 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_CONTENTS_FWD_HH +#define PALUDIS_GUARD_PALUDIS_CONTENTS_FWD_HH 1 + +#include <iosfwd> +#include <paludis/util/attributes.hh> + +/** \file + * Forward declarations for paludis/contents.hh . + * + * \ingroup g_contents + */ + +namespace paludis +{ + struct ContentsEntry; + struct ContentsFileEntry; + struct ContentsDirEntry; + struct ContentsSymEntry; + struct ContentsFifoEntry; + struct ContentsDevEntry; + struct ContentsMiscEntry; + + struct Contents; + + struct ContentsVisitorTypes; + + /** + * Write a ContentsSymEntry to a stream. + * + * \ingroup g_contents + */ + std::ostream & operator<< (std::ostream &, const ContentsSymEntry &) PALUDIS_VISIBLE; + + /** + * Write a ContentsEntry to a stream. + * + * \ingroup g_contents + */ + std::ostream & operator<< (std::ostream &, const ContentsEntry &) PALUDIS_VISIBLE; +} + +#endif diff --git a/0.26.0_alpha1/paludis/contents.cc b/0.26.0_alpha1/paludis/contents.cc new file mode 100644 index 000000000..7c3937347 --- /dev/null +++ b/0.26.0_alpha1/paludis/contents.cc @@ -0,0 +1,145 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 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 "contents.hh" +#include <paludis/util/visitor-impl.hh> +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <libwrapiter/libwrapiter_forward_iterator.hh> +#include <list> + +using namespace paludis; + +template class ConstVisitor<ContentsVisitorTypes>; +template class ConstAcceptInterface<ContentsVisitorTypes>; + +template class ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsFileEntry>; +template class ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsDirEntry>; +template class ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsSymEntry>; +template class ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsFifoEntry>; +template class ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsDevEntry>; +template class ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsMiscEntry>; + +template class Visits<const ContentsFileEntry>; +template class Visits<const ContentsDirEntry>; +template class Visits<const ContentsSymEntry>; +template class Visits<const ContentsFifoEntry>; +template class Visits<const ContentsDevEntry>; +template class Visits<const ContentsMiscEntry>; + +ContentsEntry::ContentsEntry(const std::string & n) : + _name(n) +{ +} + +ContentsEntry::~ContentsEntry() +{ +} + +std::string +ContentsEntry::name() const +{ + return _name; +} + +ContentsFileEntry::ContentsFileEntry(const std::string & our_name) : + ContentsEntry(our_name) +{ +} + +ContentsDirEntry::ContentsDirEntry(const std::string & our_name) : + ContentsEntry(our_name) +{ +} + +ContentsMiscEntry::ContentsMiscEntry(const std::string & our_name) : + ContentsEntry(our_name) +{ +} + +ContentsFifoEntry::ContentsFifoEntry(const std::string & our_name) : + ContentsEntry(our_name) +{ +} + +ContentsDevEntry::ContentsDevEntry(const std::string & our_name) : + ContentsEntry(our_name) +{ +} + +ContentsSymEntry::ContentsSymEntry(const std::string & our_name, const std::string & our_target) : + ContentsEntry(our_name), + _target(our_target) +{ +} + +std::string +ContentsSymEntry::target() const +{ + return _target; +} + +namespace paludis +{ + template<> + struct Implementation<Contents> + { + std::list<tr1::shared_ptr<const ContentsEntry> > c; + }; +} + +Contents::Contents() : + PrivateImplementationPattern<Contents>(new Implementation<Contents>()) +{ +} + +Contents::~Contents() +{ +} + +void +Contents::add(tr1::shared_ptr<const ContentsEntry> c) +{ + _imp->c.push_back(c); +} + +Contents::ConstIterator +Contents::begin() const +{ + return ConstIterator(_imp->c.begin()); +} + +Contents::ConstIterator +Contents::end() const +{ + return ConstIterator(_imp->c.end()); +} + +std::ostream & +paludis::operator<< (std::ostream & s, const ContentsSymEntry & e) +{ + s << e.name() << " -> " << e.target(); + return s; +} + +std::ostream & +paludis::operator<< (std::ostream & s, const ContentsEntry & e) +{ + s << e.name(); + return s; +} diff --git a/0.26.0_alpha1/paludis/contents.hh b/0.26.0_alpha1/paludis/contents.hh new file mode 100644 index 000000000..ab51d9bf3 --- /dev/null +++ b/0.26.0_alpha1/paludis/contents.hh @@ -0,0 +1,255 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_CONTENTS_HH +#define PALUDIS_GUARD_PALUDIS_CONTENTS_HH 1 + +#include <paludis/contents-fwd.hh> + +#include <paludis/util/visitor.hh> +#include <paludis/util/instantiation_policy.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <paludis/util/tr1_memory.hh> + +#include <string> +#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh> + +/** \file + * Declarations for the Contents classes. + * + * \ingroup g_contents + * + * \section Examples + * + * - \ref example_contents.cc "example_contents.cc" + */ + +namespace paludis +{ + /** + * Visit a contents heirarchy. + * + * \ingroup g_contents + * \nosubgrouping + */ + struct ContentsVisitorTypes : + VisitorTypes< + ContentsVisitorTypes, + ContentsEntry, + ContentsFileEntry, + ContentsDirEntry, + ContentsSymEntry, + ContentsFifoEntry, + ContentsDevEntry, + ContentsMiscEntry + > + { + }; + + /** + * Base class for a contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsEntry : + private InstantiationPolicy<ContentsEntry, instantiation_method::NonCopyableTag>, + public virtual ConstAcceptInterface<ContentsVisitorTypes> + { + private: + std::string _name; + + protected: + ///\name Basic operations + ///\{ + + ContentsEntry(const std::string & our_name); + + ///\} + + public: + ///\name Basic operations + ///\{ + + virtual ~ContentsEntry(); + + ///\} + + /// Our name. + std::string name() const PALUDIS_ATTRIBUTE((warn_unused_result)); + }; + + /** + * A file contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsFileEntry : + public ContentsEntry, + public ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsFileEntry> + { + public: + ///\name Basic operations + ///\{ + + ContentsFileEntry(const std::string & name); + + ///\} + }; + + /** + * A directory contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsDirEntry : + public ContentsEntry, + public ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsDirEntry> + { + public: + ///\name Basic operations + ///\{ + + ContentsDirEntry(const std::string & name); + + ///\} + }; + + /** + * A misc contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsMiscEntry : + public ContentsEntry, + public ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsMiscEntry> + { + public: + ///\name Basic operations + ///\{ + + ContentsMiscEntry(const std::string & name); + + ///\} + }; + + /** + * A fifo contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsFifoEntry : + public ContentsEntry, + public ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsFifoEntry> + { + public: + ///\name Basic operations + ///\{ + + ContentsFifoEntry(const std::string & name); + + ///\} + }; + + /** + * A device contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsDevEntry : + public ContentsEntry, + public ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsDevEntry> + { + public: + ///\name Basic operations + ///\{ + + ContentsDevEntry(const std::string & name); + + ///\} + }; + + /** + * A sym contents entry. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE ContentsSymEntry : + public ContentsEntry, + public ConstAcceptInterfaceVisitsThis<ContentsVisitorTypes, ContentsSymEntry> + { + private: + std::string _target; + + public: + ///\name Basic operations + ///\{ + + ContentsSymEntry(const std::string & name, const std::string & target); + + ///\} + + /// Our target (as per readlink). + std::string target() const PALUDIS_ATTRIBUTE((warn_unused_result)); + }; + + /** + * A package's contents, obtainable by PackageID::contents_key. + * + * \ingroup g_contents + * \nosubgrouping + */ + class PALUDIS_VISIBLE Contents : + private InstantiationPolicy<Contents, instantiation_method::NonCopyableTag>, + private PrivateImplementationPattern<Contents> + { + public: + ///\name Basic operations + ///\{ + + Contents(); + ~Contents(); + + ///\} + + /// Add a new entry. + void add(tr1::shared_ptr<const ContentsEntry> c); + + ///\name Iterate over our entries + ///\{ + + typedef libwrapiter::ForwardIterator<Contents, const tr1::shared_ptr<const ContentsEntry> > ConstIterator; + + ConstIterator begin() const + PALUDIS_ATTRIBUTE((warn_unused_result)); + + ConstIterator end() const + PALUDIS_ATTRIBUTE((warn_unused_result)); + + ///\} + }; +} + +#endif diff --git a/0.26.0_alpha1/paludis/dep_label-fwd.hh b/0.26.0_alpha1/paludis/dep_label-fwd.hh new file mode 100644 index 000000000..68a2056fd --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_label-fwd.hh @@ -0,0 +1,192 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_DEP_LABEL_FWD_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LABEL_FWD_HH 1 + +#include <paludis/util/attributes.hh> +#include <iosfwd> + +/** \file + * Forward declarations for paludis/dep_label.hh . + * + * \ingroup g_dep_spec + */ + +namespace paludis +{ + struct URILabelVisitorTypes; + struct URILabel; + + template <typename T_> struct ConcreteURILabel; + typedef ConcreteURILabel<enum URIMirrorsThenListedLabelTag { }> URIMirrorsThenListedLabel; + typedef ConcreteURILabel<enum URIMirrorsOnlyLabelTag { }> URIMirrorsOnlyLabel; + typedef ConcreteURILabel<enum URIListedOnlyLabelTag { }> URIListedOnlyLabel; + typedef ConcreteURILabel<enum URIListedThenMirrorsLabelTag { }> URIListedThenMirrorsLabel; + typedef ConcreteURILabel<enum URILocalMirrorsOnlyLabelTag { }> URILocalMirrorsOnlyLabel; + typedef ConcreteURILabel<enum URIManualOnlyLabelTag { }> URIManualOnlyLabel; + + /** + * A URILabel can be written to a stream. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + std::ostream & operator<< (std::ostream &, const URILabel &) PALUDIS_VISIBLE; + + struct DependencyLabelVisitorTypes; + struct DependencyLabel; + struct DependencySystemLabel; + struct DependencyTypeLabel; + struct DependencySuggestLabel; + struct DependencyABIsLabel; + + template <typename T_, typename Category_> struct ConcreteDependencyLabel; + + /** + * A DependencyHostLabel specifies host requirements for building a package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyHostLabelTag { }, + DependencySystemLabel> DependencyHostLabel; + + /** + * A DependencyTargetLabel specifies target requirements for building a package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyTargetLabelTag { }, + DependencySystemLabel> DependencyTargetLabel; + + /** + * A DependencyBuildLabel specifies build-time requirements for building a package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyBuildLabelTag { }, + DependencyTypeLabel> DependencyBuildLabel; + + /** + * A DependencyRunLabel specifies runtime requirements for building a package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyRunLabelTag { }, + DependencyTypeLabel> DependencyRunLabel; + + /** + * A DependencyInstallLabel specifies install-time requirements for building a package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyInstallLabelTag { }, + DependencyTypeLabel> DependencyInstallLabel; + + /** + * A DependencyCompileLabel specifies compiled-against requirements for building a package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyCompileLabelTag { }, + DependencyTypeLabel> DependencyCompileLabel; + + /** + * A DependencySuggestLabel specifies that a dependency is suggested. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencySuggestedLabelTag { }, + DependencySuggestLabel> DependencySuggestedLabel; + + /** + * A DependencyRecommendedLabel specifies that a dependency is recommended. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyRecommendedLabelTag { }, + DependencySuggestLabel> DependencyRecommendedLabel; + + /** + * A DependencyRequiredLabel specifies that a dependency is required. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyRequiredLabelTag { }, + DependencySuggestLabel> DependencyRequiredLabel; + + /** + * A DependencyAnyLabel specifies that a dependency can be satisfied by + * any ABI. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyAnyLabelTag { }, + DependencyABIsLabel> DependencyAnyLabel; + + /** + * A DependencyMineLabel specifies that a dependency is satisfied by + * ABIs equal to those being used to create the depending package. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyMineLabelTag { }, + DependencyABIsLabel> DependencyMineLabel; + + /** + * A DependencyPrimaryLabel specifies that a dependency can be satisfied by + * the primary ABI. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyPrimaryLabelTag { }, + DependencyABIsLabel> DependencyPrimaryLabel; + + /** + * A DependencyABILabel specifies that a dependency can be satisfied by + * a named ABI. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + typedef ConcreteDependencyLabel<enum DependencyABILabelTag { }, + DependencyABIsLabel> DependencyABILabel; + + /** + * A DependencyLabel can be written to a stream. + * + * \ingroup g_dep_spec + * \since 0.26 + */ + std::ostream & operator<< (std::ostream &, const DependencyLabel &) PALUDIS_VISIBLE; +} + +#endif diff --git a/0.26.0_alpha1/paludis/dep_label.cc b/0.26.0_alpha1/paludis/dep_label.cc new file mode 100644 index 000000000..34580f656 --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_label.cc @@ -0,0 +1,140 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 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 <paludis/dep_label.hh> +#include <paludis/util/visitor-impl.hh> +#include <ostream> + +using namespace paludis; + +std::ostream & +paludis::operator<< (std::ostream & s, const URILabel & l) +{ + s << l.text(); + return s; +} + +std::ostream & +paludis::operator<< (std::ostream & s, const DependencyLabel & l) +{ + s << l.text(); + return s; +} + +URILabel::~URILabel() +{ +} + +namespace paludis +{ + template <> + template <typename T_> + struct Implementation<ConcreteURILabel<T_> > + { + const std::string text; + + Implementation(const std::string & t) : + text(t) + { + } + }; +} + +template <typename T_> +ConcreteURILabel<T_>::ConcreteURILabel(const std::string & t) : + PrivateImplementationPattern<ConcreteURILabel<T_> >(new Implementation<ConcreteURILabel<T_> >(t)) +{ +} + +template <typename T_> +ConcreteURILabel<T_>::~ConcreteURILabel() +{ +} + +template <typename T_> +const std::string +ConcreteURILabel<T_>::text() const +{ + return _imp->text; +} + +template class ConcreteURILabel<URIMirrorsThenListedLabel::Tag>; +template class ConcreteURILabel<URIMirrorsOnlyLabel::Tag>; +template class ConcreteURILabel<URIListedOnlyLabel::Tag>; +template class ConcreteURILabel<URIListedThenMirrorsLabel::Tag>; +template class ConcreteURILabel<URILocalMirrorsOnlyLabel::Tag>; +template class ConcreteURILabel<URIManualOnlyLabel::Tag>; + +std::ostream & operator<<(std::ostream & s, const DependencyLabel & l) +{ + s << l.text(); + return s; +} + +DependencyLabel::~DependencyLabel() +{ +} + +namespace paludis +{ + template <> + template <typename T_, typename C_> + struct Implementation<ConcreteDependencyLabel<T_, C_> > + { + const std::string text; + + Implementation(const std::string & t) : + text(t) + { + } + }; +} + +template <typename T_, typename C_> +ConcreteDependencyLabel<T_, C_>::ConcreteDependencyLabel(const std::string & t) : + PrivateImplementationPattern<ConcreteDependencyLabel<T_, C_> >(new Implementation<ConcreteDependencyLabel<T_, C_> >(t)) +{ +} + +template <typename T_, typename C_> +ConcreteDependencyLabel<T_, C_>::~ConcreteDependencyLabel() +{ +} + +template <typename T_, typename C_> +const std::string +ConcreteDependencyLabel<T_, C_>::text() const +{ + return _imp->text; +} + +template class ConcreteDependencyLabel<DependencyHostLabel::Tag, DependencySystemLabel>; +template class ConcreteDependencyLabel<DependencyTargetLabel::Tag, DependencySystemLabel>; +template class ConcreteDependencyLabel<DependencyBuildLabel::Tag, DependencyTypeLabel>; +template class ConcreteDependencyLabel<DependencyRunLabel::Tag, DependencyTypeLabel>; +template class ConcreteDependencyLabel<DependencyInstallLabel::Tag, DependencyTypeLabel>; +template class ConcreteDependencyLabel<DependencyCompileLabel::Tag, DependencyTypeLabel>; +template class ConcreteDependencyLabel<DependencySuggestedLabel::Tag, DependencySuggestLabel>; +template class ConcreteDependencyLabel<DependencyRecommendedLabel::Tag, DependencySuggestLabel>; +template class ConcreteDependencyLabel<DependencyRequiredLabel::Tag, DependencySuggestLabel>; +template class ConcreteDependencyLabel<DependencyAnyLabel::Tag, DependencyABIsLabel>; +template class ConcreteDependencyLabel<DependencyMineLabel::Tag, DependencyABIsLabel>; +template class ConcreteDependencyLabel<DependencyPrimaryLabel::Tag, DependencyABIsLabel>; +template class ConcreteDependencyLabel<DependencyABILabel::Tag, DependencyABIsLabel>; + diff --git a/0.26.0_alpha1/paludis/dep_label.hh b/0.26.0_alpha1/paludis/dep_label.hh new file mode 100644 index 000000000..1b8bfc592 --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_label.hh @@ -0,0 +1,330 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_DEP_LABEL_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LABEL_HH 1 + +#include <paludis/dep_label-fwd.hh> +#include <paludis/util/visitor.hh> +#include <paludis/util/instantiation_policy.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <paludis/util/attributes.hh> + +/** \file + * Declarations for dependency label-related classes. + * + * \ingroup g_dep_spec + * + * \section Examples + * + * - \ref example_dep_label.cc "example_dep_label.cc" + * - \ref example_dep_spec.cc "example_dep_spec.cc" (for specifications) + * - \ref example_dep_tree.cc "example_dep_tree.cc" (for specification trees) + * - \ref example_dep_tag.cc "example_dep_tag.cc" (for tags) + */ + +namespace paludis +{ + /** + * Types for visiting a URI label. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct URILabelVisitorTypes : + VisitorTypes< + URILabelVisitorTypes, + URILabel, + URIMirrorsThenListedLabel, + URIMirrorsOnlyLabel, + URIListedOnlyLabel, + URIListedThenMirrorsLabel, + URILocalMirrorsOnlyLabel, + URIManualOnlyLabel + > + { + }; + + /** + * Types for visiting a dependency label. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct DependencyLabelVisitorTypes : + VisitorTypes< + DependencyLabelVisitorTypes, + DependencyLabel, + DependencySystemLabel, + DependencyTypeLabel, + DependencySuggestLabel, + DependencyABIsLabel + > + { + }; + + /** + * Types for visiting a dependency system label. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct DependencySystemLabelVisitorTypes : + VisitorTypes< + DependencySystemLabelVisitorTypes, + DependencySystemLabel, + DependencyHostLabel, + DependencyTargetLabel + > + { + }; + + /** + * Types for visiting a dependency type label. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct DependencyTypeLabelVisitorTypes : + VisitorTypes< + DependencyTypeLabelVisitorTypes, + DependencyTypeLabel, + DependencyBuildLabel, + DependencyRunLabel, + DependencyInstallLabel, + DependencyCompileLabel + > + { + }; + + /** + * Types for visiting a dependency suggests label. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct DependencySuggestLabelVisitorTypes : + VisitorTypes< + DependencySuggestLabelVisitorTypes, + DependencySuggestLabel, + DependencySuggestedLabel, + DependencyRecommendedLabel, + DependencyRequiredLabel + > + { + }; + + /** + * Types for visiting a dependency abi label. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct DependencyABIsLabelVisitorTypes : + VisitorTypes< + DependencyABIsLabelVisitorTypes, + DependencyABIsLabel, + DependencyAnyLabel, + DependencyMineLabel, + DependencyPrimaryLabel, + DependencyABILabel + > + { + }; + + /** + * URI label base class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + class PALUDIS_VISIBLE URILabel : + private InstantiationPolicy<URILabel, instantiation_method::NonCopyableTag>, + public virtual ConstAcceptInterface<URILabelVisitorTypes> + { + public: + ///\name Basic operations + ///\{ + + virtual ~URILabel() = 0; + + ///\} + + /// Our text. + virtual const std::string text() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + }; + + /** + * A concrete URI label class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + template <typename T_> + class PALUDIS_VISIBLE ConcreteURILabel : + public URILabel, + public ConstAcceptInterfaceVisitsThis<URILabelVisitorTypes, ConcreteURILabel<T_> >, + private PrivateImplementationPattern<ConcreteURILabel<T_> > + { + private: + using PrivateImplementationPattern<ConcreteURILabel<T_> >::_imp; + + public: + ///\name Basic operations + ///\{ + + ConcreteURILabel(const std::string &); + ~ConcreteURILabel(); + + ///\} + + virtual const std::string text() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + /// Convenience typedef alias to obtain our tag. + typedef T_ Tag; + }; + + /** + * Dependency label base class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + class PALUDIS_VISIBLE DependencyLabel : + private InstantiationPolicy<DependencyLabel, instantiation_method::NonCopyableTag>, + public virtual ConstAcceptInterface<DependencyLabelVisitorTypes> + { + public: + ///\name Basic operations + ///\{ + + virtual ~DependencyLabel() = 0; + + ///\} + + /// Our text. + virtual const std::string text() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0; + }; + + /** + * System dependency label base class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct PALUDIS_VISIBLE DependencySystemLabel : + public DependencyLabel, + public ConstAcceptInterfaceVisitsThis<DependencyLabelVisitorTypes, DependencySystemLabel>, + public virtual ConstAcceptInterface<DependencySystemLabelVisitorTypes> + { + /// Convenience alias for our visitor types. + typedef DependencySystemLabelVisitorTypes VisitorTypes; + }; + + /** + * Type dependency label base class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct PALUDIS_VISIBLE DependencyTypeLabel : + public DependencyLabel, + public ConstAcceptInterfaceVisitsThis<DependencyLabelVisitorTypes, DependencyTypeLabel>, + public virtual ConstAcceptInterface<DependencyTypeLabelVisitorTypes> + { + /// Convenience alias for our visitor types. + typedef DependencyTypeLabelVisitorTypes VisitorTypes; + }; + + /** + * Suggest dependency label base class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct PALUDIS_VISIBLE DependencySuggestLabel : + public DependencyLabel, + public ConstAcceptInterfaceVisitsThis<DependencyLabelVisitorTypes, DependencySuggestLabel>, + public virtual ConstAcceptInterface<DependencySuggestLabelVisitorTypes> + { + /// Convenience alias for our visitor types. + typedef DependencySuggestLabelVisitorTypes VisitorTypes; + }; + + /** + * ABI dependency label base class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + struct PALUDIS_VISIBLE DependencyABIsLabel : + public DependencyLabel, + public ConstAcceptInterfaceVisitsThis<DependencyLabelVisitorTypes, DependencyABIsLabel>, + public virtual ConstAcceptInterface<DependencyABIsLabelVisitorTypes> + { + /// Convenience alias for our visitor types. + typedef DependencyABIsLabelVisitorTypes VisitorTypes; + }; + + /** + * A concrete dependency label class. + * + * \since 0.26 + * \ingroup g_dep_spec + * \nosubgrouping + */ + template <typename T_, typename C_> + class PALUDIS_VISIBLE ConcreteDependencyLabel : + public C_, + public ConstAcceptInterfaceVisitsThis<typename C_::VisitorTypes, ConcreteDependencyLabel<T_, C_> >, + private PrivateImplementationPattern<ConcreteDependencyLabel<T_, C_> > + { + private: + using PrivateImplementationPattern<ConcreteDependencyLabel<T_, C_> >::_imp; + + public: + ///\name Basic operations + ///\{ + + ConcreteDependencyLabel(const std::string &); + ~ConcreteDependencyLabel(); + + ///\} + + virtual const std::string text() const PALUDIS_ATTRIBUTE((warn_unused_result)); + + /// Convenience typedef alias to obtain our tag. + typedef T_ Tag; + }; +} + +#endif diff --git a/0.26.0_alpha1/paludis/dep_list-fwd.hh b/0.26.0_alpha1/paludis/dep_list-fwd.hh new file mode 100644 index 000000000..50bafee7b --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_list-fwd.hh @@ -0,0 +1,51 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_DEP_LIST_FWD_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LIST_FWD_HH 1 + +#include <paludis/util/tr1_memory.hh> +#include <paludis/repository-fwd.hh> +#include <paludis/dep_tree.hh> +#include <paludis/package_id-fwd.hh> +#include <paludis/environment-fwd.hh> + +/** \file + * Forward declarations for paludis/dep_list.hh . + * + * \ingroup g_dep_list + */ + +namespace paludis +{ + class DepListOptions; + class DepListEntryDestination; + class DepListEntry; + class DepList; + + /** + * Is an item a valid child in an AnyDepSpec? + * + * \ingroup g_dep_list + */ + bool is_viable_any_child(const Environment & env, const tr1::shared_ptr<const PackageID> &, + const DependencySpecTree::ConstItem & i); +} + +#endif diff --git a/0.26.0_alpha1/paludis/dep_list.cc b/0.26.0_alpha1/paludis/dep_list.cc new file mode 100644 index 000000000..17a7d823e --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_list.cc @@ -0,0 +1,1552 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 <paludis/dep_list.hh> +#include <paludis/dep_list_exceptions.hh> +#include <paludis/query_visitor.hh> +#include <paludis/range_rewriter.hh> +#include <paludis/show_suggest_visitor.hh> +#include <paludis/condition_tracker.hh> +#include <paludis/handled_information.hh> + +#include <paludis/dep_spec.hh> +#include <paludis/action.hh> +#include <paludis/dep_spec_flattener.hh> +#include <paludis/distribution.hh> +#include <paludis/hashed_containers.hh> +#include <paludis/match_package.hh> +#include <paludis/metadata_key.hh> +#include <paludis/query.hh> +#include <paludis/package_id.hh> +#include <paludis/version_requirements.hh> + +#include <paludis/util/iterator.hh> +#include <paludis/util/join.hh> +#include <paludis/util/log.hh> +#include <paludis/util/private_implementation_pattern-impl.hh> +#include <paludis/util/make_shared_ptr.hh> +#include <paludis/util/save.hh> +#include <paludis/util/set.hh> +#include <paludis/util/sequence.hh> +#include <paludis/util/stringify.hh> +#include <paludis/util/tokeniser.hh> +#include <paludis/util/tr1_functional.hh> +#include <paludis/util/visitor-impl.hh> + +#include <libwrapiter/libwrapiter_forward_iterator.hh> +#include <libwrapiter/libwrapiter_output_iterator.hh> + +#include <algorithm> +#include <functional> +#include <vector> +#include <list> +#include <set> + +using namespace paludis; + +template class Sequence<tr1::function<bool (const PackageID &, const Mask &)> >; + +#include <paludis/dep_list-sr.cc> + +DepListOptions::DepListOptions() : + reinstall(dl_reinstall_never), + reinstall_scm(dl_reinstall_scm_never), + target_type(dl_target_package), + upgrade(dl_upgrade_always), + downgrade(dl_downgrade_as_needed), + new_slots(dl_new_slots_always), + fall_back(dl_fall_back_as_needed_except_targets), + installed_deps_pre(dl_deps_discard), + installed_deps_runtime(dl_deps_try_post), + installed_deps_post(dl_deps_try_post), + uninstalled_deps_pre(dl_deps_pre), + uninstalled_deps_runtime(dl_deps_pre_or_post), + uninstalled_deps_post(dl_deps_post), + uninstalled_deps_suggested(dl_deps_try_post), + suggested(dl_suggested_show), + circular(dl_circular_error), + use(dl_use_deps_standard), + blocks(dl_blocks_accumulate), + dependency_tags(false) +{ + /* when changing the above, also see src/paludis/command_line.cc. */ +} + +namespace paludis +{ + typedef std::list<DepListEntry> MergeList; + typedef MakeHashedMultiMap<QualifiedPackageName, MergeList::iterator>::Type MergeListIndex; + + template<> + struct Implementation<DepList> + { + const Environment * const env; + tr1::shared_ptr<DepListOptions> opts; + + MergeList merge_list; + MergeList::const_iterator current_merge_list_entry; + MergeList::iterator merge_list_insert_position; + long merge_list_generation; + + MergeListIndex merge_list_index; + + SetSpecTree::ConstItem * current_top_level_target; + + bool throw_on_blocker; + + const tr1::shared_ptr<const PackageID> current_package_id() const + { + if (current_merge_list_entry != merge_list.end()) + return current_merge_list_entry->package_id; + return tr1::shared_ptr<const PackageID>(); + } + + Implementation(const Environment * const e, const DepListOptions & o) : + env(e), + opts(new DepListOptions(o)), + current_merge_list_entry(merge_list.end()), + merge_list_insert_position(merge_list.end()), + merge_list_generation(0), + current_top_level_target(0), + throw_on_blocker(o.blocks == dl_blocks_error) + { + } + }; +} + +namespace +{ + struct GenerationGreaterThan + { + long g; + + GenerationGreaterThan(long gg) : + g(gg) + { + } + + template <typename T_> + bool operator() (const T_ & e) const + { + return e.generation > g; + } + }; + + struct RemoveTagsWithGenerationGreaterThan + { + long g; + + RemoveTagsWithGenerationGreaterThan(long gg) : + g(gg) + { + } + + void operator() (DepListEntry & e) const + { + /* see EffSTL 9 for why this is so painful */ + if (e.tags->empty()) + return; + tr1::shared_ptr<DepListEntryTags> t(new DepListEntryTags); + GenerationGreaterThan pred(g); + for (DepListEntryTags::ConstIterator i(e.tags->begin()), i_end(e.tags->end()) ; + i != i_end ; ++i) + if (! pred(*i)) + t->insert(*i); + std::swap(e.tags, t); + } + }; + + class DepListTransaction + { + protected: + MergeList & _list; + MergeListIndex & _index; + long & _generation; + int _initial_generation; + bool _committed; + + public: + DepListTransaction(MergeList & l, MergeListIndex & i, long & g) : + _list(l), + _index(i), + _generation(g), + _initial_generation(g), + _committed(false) + { + ++_generation; + } + + void commit() + { + _committed = true; + } + + ~DepListTransaction() + { + if (_committed) + return; + + /* See EffSTL 9 */ + GenerationGreaterThan pred(_initial_generation); + for (MergeList::iterator i(_list.begin()) ; i != _list.end() ; ) + { + if (! pred(*i)) + ++i; + else + { + for (std::pair<MergeListIndex::iterator, MergeListIndex::iterator> p( + _index.equal_range(i->package_id->name())) ; p.first != p.second ; ) + if (p.first->second == i) + _index.erase(p.first++); + else + ++p.first; + + _list.erase(i++); + } + } + + std::for_each(_list.begin(), _list.end(), + RemoveTagsWithGenerationGreaterThan(_initial_generation)); + } + }; + + struct MatchDepListEntryAgainstPackageDepSpec + { + const Environment * const env; + const PackageDepSpec & a; + + MatchDepListEntryAgainstPackageDepSpec(const Environment * const ee, + const PackageDepSpec & aa) : + env(ee), + a(aa) + { + } + + bool operator() (const std::pair<const QualifiedPackageName, MergeList::const_iterator> & e) + { + switch (e.second->kind) + { + case dlk_virtual: + case dlk_package: + case dlk_provided: + case dlk_already_installed: + case dlk_subpackage: + return match_package(*env, a, *e.second->package_id); + + case dlk_block: + case dlk_masked: + case dlk_suggested: + return false; + + case last_dlk: + ; + } + + throw InternalError(PALUDIS_HERE, "Bad e.second->kind"); + } + }; + + bool is_interesting_any_child(const Environment & env, + const DependencySpecTree::ConstItem & i) + { + const PackageDepSpec * const u(get_const_item(i)->as_package_dep_spec()); + if (0 != u && u->package_ptr()) + { + return ! env.package_database()->query( + query::SupportsAction<InstalledAction>() & + query::Matches(PackageDepSpec( + tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName(*u->package_ptr())))), + qo_whatever)->empty(); + } + else + return false; + } +} + +struct DepList::AddVisitor : + ConstVisitor<DependencySpecTree>, + ConstVisitor<DependencySpecTree>::VisitConstSequence<AddVisitor, AllDepSpec> +{ + DepList * const d; + tr1::shared_ptr<const DestinationsSet> destinations; + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > conditions; + std::set<SetName> recursing_sets; + + AddVisitor(DepList * const dd, tr1::shared_ptr<const DestinationsSet> ddd, + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > c = + (tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> >( + new ConstTreeSequence<DependencySpecTree, AllDepSpec>( + tr1::shared_ptr<AllDepSpec>(new AllDepSpec))))) : + d(dd), + destinations(ddd), + conditions(c) + { + } + + using ConstVisitor<DependencySpecTree>::VisitConstSequence<AddVisitor, AllDepSpec>::visit_sequence; + + void visit_sequence(const AnyDepSpec &, + DependencySpecTree::ConstSequenceIterator, + DependencySpecTree::ConstSequenceIterator); + + void visit_sequence(const UseDepSpec &, + DependencySpecTree::ConstSequenceIterator, + DependencySpecTree::ConstSequenceIterator); + + void visit_leaf(const PackageDepSpec &); + + void visit_leaf(const BlockDepSpec &); + + void visit_leaf(const DependencyLabelsDepSpec &); + + void visit_leaf(const NamedSetDepSpec &); +}; + +void +DepList::AddVisitor::visit_leaf(const PackageDepSpec & a) +{ + Context context("When adding PackageDepSpec '" + stringify(a) + "':"); + + Save<tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > > save_c( + &conditions, d->_imp->opts->dependency_tags ? ConditionTracker(conditions).add_condition(a) : conditions); + + /* find already installed things */ + // TODO: check destinations + tr1::shared_ptr<const PackageIDSequence> already_installed(d->_imp->env->package_database()->query( + query::SupportsAction<InstalledAction>() & + query::Matches(a), + qo_order_by_version)); + + /* are we already on the merge list? */ + std::pair<MergeListIndex::iterator, MergeListIndex::iterator> q; + if (a.package_ptr()) + q = d->_imp->merge_list_index.equal_range(*a.package_ptr()); + else + q = std::make_pair(d->_imp->merge_list_index.begin(), d->_imp->merge_list_index.end()); + + MergeListIndex::iterator qq(std::find_if(q.first, q.second, + MatchDepListEntryAgainstPackageDepSpec(d->_imp->env, a))); + + MergeList::iterator existing_merge_list_entry(qq == q.second ? d->_imp->merge_list.end() : qq->second); + if (existing_merge_list_entry != d->_imp->merge_list.end()) + { + /* tag it */ + if (a.tag()) + existing_merge_list_entry->tags->insert(DepTagEntry::create() + .tag(a.tag()) + .generation(d->_imp->merge_list_generation)); + + if (d->_imp->opts->dependency_tags && d->_imp->current_package_id()) + existing_merge_list_entry->tags->insert(DepTagEntry::create() + .tag(tr1::shared_ptr<DepTag>(new DependencyDepTag(d->_imp->current_package_id(), a, conditions))) + .generation(d->_imp->merge_list_generation)); + + /* add an appropriate destination */ + // TODO + + /* have our deps been merged already, or is this a circular dep? */ + if (dle_no_deps == existing_merge_list_entry->state) + { + /* is a sufficiently good version installed? */ + if (! already_installed->empty()) + return; + + if (d->_imp->opts->circular == dl_circular_discard) + { + Log::get_instance()->message(ll_qa, lc_context, "Dropping circular dependency on '" + + stringify(*existing_merge_list_entry->package_id) + "'"); + return; + } + else if (d->_imp->opts->circular == dl_circular_discard_silently) + return; + + throw CircularDependencyError("Atom '" + stringify(a) + "' matched by merge list entry '" + + stringify(*existing_merge_list_entry->package_id) + "', which does not yet have its " + "dependencies installed"); + } + else + return; + } + + /* find installable candidates, and find the best visible candidate */ + tr1::shared_ptr<const PackageID> best_visible_candidate; + tr1::shared_ptr<const PackageIDSequence> installable_candidates( + d->_imp->env->package_database()->query( + query::MaybeSupportsAction<InstallAction>() & + query::Matches(a), + qo_order_by_version)); + + for (PackageIDSequence::ReverseConstIterator p(installable_candidates->rbegin()), + p_end(installable_candidates->rend()) ; p != p_end ; ++p) + if ((*p)->supports_action(SupportsActionTest<InstallAction>()) && ! (*p)->masked()) + { + best_visible_candidate = *p; + break; + } + + /* are we allowed to override mask reasons? */ + if (! best_visible_candidate && d->_imp->opts->override_masks) + { + for (DepListOverrideMasksFunctions::ConstIterator of(d->_imp->opts->override_masks->begin()), + of_end(d->_imp->opts->override_masks->end()) ; of != of_end ; ++of) + { + if (best_visible_candidate) + break; + + for (PackageIDSequence::ReverseConstIterator p(installable_candidates->rbegin()), + p_end(installable_candidates->rend()) ; p != p_end ; ++p) + { + if (! (*p)->supports_action(SupportsActionTest<InstallAction>())) + continue; + + bool success(true); + for (PackageID::MasksConstIterator m((*p)->begin_masks()), m_end((*p)->end_masks()) ; + m != m_end ; ++m) + { + bool local_success(false); + for (DepListOverrideMasksFunctions::ConstIterator o(d->_imp->opts->override_masks->begin()), + o_end(next(of)) ; o != o_end ; ++o) + if ((*o)(**p, **m)) + local_success = true; + + success &= local_success; + if (! success) + break; + } + + if (success) + { + d->add_error_package(*p, dlk_masked, a, conditions); + best_visible_candidate = *p; + } + } + } + } + + /* no installable candidates. if we're already installed, that's ok (except for top level + * package targets), otherwise error. */ + if (! best_visible_candidate) + { + bool can_fall_back; + do + { + switch (d->_imp->opts->fall_back) + { + case dl_fall_back_never: + can_fall_back = false; + continue; + + case dl_fall_back_as_needed_except_targets: + if (! d->_imp->current_package_id()) + can_fall_back = false; + else if (already_installed->empty()) + can_fall_back = true; + else + can_fall_back = ! d->is_top_level_target(**already_installed->last()); + + continue; + + case dl_fall_back_as_needed: + can_fall_back = true; + continue; + + case last_dl_fall_back: + ; + } + + throw InternalError(PALUDIS_HERE, "Bad fall_back value '" + stringify(d->_imp->opts->fall_back) + "'"); + } while (false); + + if (already_installed->empty() || ! can_fall_back) + { + if (! a.use_requirements_ptr()) + throw AllMaskedError(a); + + tr1::shared_ptr<const PackageIDSequence> match_except_reqs(d->_imp->env->package_database()->query( + query::Matches(*a.without_use_requirements()), qo_whatever)); + + for (PackageIDSequence::ConstIterator i(match_except_reqs->begin()), + i_end(match_except_reqs->end()) ; i != i_end ; ++i) + if (! (*i)->masked()) + throw UseRequirementsNotMetError(stringify(a)); + + throw AllMaskedError(a); + } + else + { + Log::get_instance()->message(ll_warning, lc_context, "No visible packages matching '" + + stringify(a) + "', falling back to installed package '" + + stringify(**already_installed->last()) + "'"); + d->add_already_installed_package(*already_installed->last(), a.tag(), a, conditions, destinations); + return; + } + } + + tr1::shared_ptr<PackageIDSequence> already_installed_in_same_slot(new PackageIDSequence); + for (PackageIDSequence::ConstIterator aa(already_installed->begin()), + aa_end(already_installed->end()) ; aa != aa_end ; ++aa) + if ((*aa)->slot() == best_visible_candidate->slot()) + already_installed_in_same_slot->push_back(*aa); + /* no need to sort already_installed_in_same_slot here, although if the above is + * changed then check that this still holds... */ + + /* we have an already installed version. do we want to use it? */ + if (! already_installed_in_same_slot->empty()) + { + if (d->prefer_installed_over_uninstalled(**already_installed_in_same_slot->last(), *best_visible_candidate)) + { + Log::get_instance()->message(ll_debug, lc_context, "Taking installed package '" + + stringify(**already_installed_in_same_slot->last()) + "' over '" + + stringify(*best_visible_candidate) + "'"); + d->add_already_installed_package(*already_installed_in_same_slot->last(), a.tag(), a, conditions, destinations); + return; + } + else + Log::get_instance()->message(ll_debug, lc_context, "Not taking installed package '" + + stringify(**already_installed_in_same_slot->last()) + "' over '" + + stringify(*best_visible_candidate) + "'"); + } + else if ((! already_installed->empty()) && (dl_new_slots_as_needed == d->_imp->opts->new_slots)) + { + /* we have an already installed, but not in the same slot, and our options + * allow us to take this. */ + if (d->prefer_installed_over_uninstalled(**already_installed->last(), *best_visible_candidate)) + { + Log::get_instance()->message(ll_debug, lc_context, "Taking installed package '" + + stringify(**already_installed->last()) + "' over '" + stringify(*best_visible_candidate) + + "' (in different slot)"); + d->add_already_installed_package(*already_installed->last(), a.tag(), a, conditions, destinations); + return; + } + else + Log::get_instance()->message(ll_debug, lc_context, "Not taking installed package '" + + stringify(**already_installed->last()) + "' over '" + + stringify(*best_visible_candidate) + "' (in different slot)"); + } + else + Log::get_instance()->message(ll_debug, lc_context) << "No installed packages in SLOT '" + << best_visible_candidate->slot() << "', taking uninstalled package '" + << *best_visible_candidate << "'"; + + /* if this is a downgrade, make sure that that's ok */ + switch (d->_imp->opts->downgrade) + { + case dl_downgrade_as_needed: + break; + + case dl_downgrade_error: + case dl_downgrade_warning: + { + tr1::shared_ptr<const PackageIDSequence> are_we_downgrading( + d->_imp->env->package_database()->query( + query::SupportsAction<InstalledAction>() & + query::Matches(PackageDepSpec( + make_shared_ptr(new QualifiedPackageName(best_visible_candidate->name())), + tr1::shared_ptr<CategoryNamePart>(), + tr1::shared_ptr<PackageNamePart>(), + tr1::shared_ptr<VersionRequirements>(), + vr_and, + make_shared_ptr(new SlotName(best_visible_candidate->slot())))), + qo_order_by_version)); + + if (are_we_downgrading->empty()) + break; + + if ((*are_we_downgrading->last())->version() <= best_visible_candidate->version()) + break; + + if (d->_imp->opts->downgrade == dl_downgrade_error) + throw DowngradeNotAllowedError(stringify(*best_visible_candidate), + stringify(**are_we_downgrading->last())); + + Log::get_instance()->message(ll_warning, lc_context) << "Downgrade to '" + << *best_visible_candidate << "' from '" << **are_we_downgrading->last() << "' forced"; + } + break; + + case last_dl_downgrade: + ; + } + + d->add_package(best_visible_candidate, a.tag(), a, conditions, destinations); +} + +void +DepList::AddVisitor::visit_leaf(const NamedSetDepSpec & a) +{ + Context context("When adding NamedSetDepSpec '" + stringify(a) + "':"); + + tr1::shared_ptr<const SetSpecTree::ConstItem> set(d->_imp->env->set(a.name())); + + if (! set) + throw NoSuchSetError(stringify(a.name())); + + if (! recursing_sets.insert(a.name()).second) + { + Log::get_instance()->message(ll_warning, lc_context) << "Recursively defined set '" << a.name() << "'"; + throw RecursivelyDefinedSetError(stringify(a.name())); + } + + set->accept(*this); + + recursing_sets.erase(a.name()); +} + +void +DepList::AddVisitor::visit_sequence(const UseDepSpec & a, + DependencySpecTree::ConstSequenceIterator cur, + DependencySpecTree::ConstSequenceIterator end) +{ + Save<tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > > save_c( + &conditions, d->_imp->opts->dependency_tags ? ConditionTracker(conditions).add_condition(a) : conditions); + + if (d->_imp->opts->use == dl_use_deps_standard) + { + if ((d->_imp->current_package_id() ? d->_imp->env->query_use(a.flag(), *d->_imp->current_package_id()) : false) ^ a.inverse()) + std::for_each(cur, end, accept_visitor(*this)); + } + else + { + RepositoryUseInterface * u(0); + if ((! d->_imp->current_package_id()) || (! ((u = d->_imp->current_package_id()->repository()->use_interface)))) + std::for_each(cur, end, accept_visitor(*this)); + else if (a.inverse()) + { + if ((! d->_imp->current_package_id()) || (! u->query_use_force(a.flag(), *d->_imp->current_package_id()))) + std::for_each(cur, end, accept_visitor(*this)); + } + else + { + if ((! d->_imp->current_package_id()) || (! u->query_use_mask(a.flag(), *d->_imp->current_package_id()))) + std::for_each(cur, end, accept_visitor(*this)); + } + } +} + +void +DepList::AddVisitor::visit_sequence(const AnyDepSpec & a, + DependencySpecTree::ConstSequenceIterator cur, + DependencySpecTree::ConstSequenceIterator end) +{ + using namespace tr1::placeholders; + + /* annoying requirement: || ( foo? ( ... ) ) resolves to empty if !foo. */ + if (end == std::find_if(cur, end, + tr1::bind(&is_viable_any_child, tr1::cref(*d->_imp->env), d->_imp->current_package_id(), _1))) + return; + + RangeRewriter r; + std::for_each(cur, end, accept_visitor(r)); + if (r.spec()) + { + Context context("When using rewritten range '" + stringify(*r.spec()) + "':"); + TreeLeaf<DependencySpecTree, PackageDepSpec> rr(r.spec()); + d->add_not_top_level(rr, destinations, conditions); + return; + } + + Save<tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > > save_c( + &conditions, d->_imp->opts->dependency_tags ? ConditionTracker(conditions).add_condition(a) : conditions); + + /* see if any of our children is already installed. if any is, add it so that + * any upgrades kick in */ + for (DependencySpecTree::ConstSequenceIterator c(cur) ; c != end ; ++c) + { + if (! is_viable_any_child(*d->_imp->env, d->_imp->current_package_id(), *c)) + continue; + + if (d->already_installed(*c, destinations)) + { + Context context("When using already installed group to resolve dependencies:"); + d->add_not_top_level(*c, destinations, conditions); + return; + } + } + + /* if we have something like || ( a >=b-2 ) and b-1 is installed, try to go for + * the b-2 bit first */ + for (DependencySpecTree::ConstSequenceIterator c(cur) ; c != end ; ++c) + { + if (! is_viable_any_child(*d->_imp->env, d->_imp->current_package_id(), *c)) + continue; + if (! is_interesting_any_child(*d->_imp->env, *c)) + continue; + + try + { + Context context("When using already installed package to resolve dependencies:"); + + Save<bool> save_t(&d->_imp->throw_on_blocker, + dl_blocks_discard_completely != d->_imp->opts->blocks); + Save<tr1::shared_ptr<DepListOverrideMasksFunctions> > save_o(&d->_imp->opts->override_masks, + tr1::shared_ptr<DepListOverrideMasksFunctions>()); + d->add_not_top_level(*c, destinations, conditions); + return; + } + catch (const DepListError &) + { + } + } + + /* install first available viable option */ + for (DependencySpecTree::ConstSequenceIterator c(cur) ; c != end ; ++c) + { + if (! is_viable_any_child(*d->_imp->env, d->_imp->current_package_id(), *c)) + continue; + + try + { + Context context("When using new group to resolve dependencies:"); + + Save<bool> save_t(&d->_imp->throw_on_blocker, + dl_blocks_discard_completely != d->_imp->opts->blocks); + Save<tr1::shared_ptr<DepListOverrideMasksFunctions> > save_o(&d->_imp->opts->override_masks, + tr1::shared_ptr<DepListOverrideMasksFunctions>()); + d->add_not_top_level(*c, destinations, conditions); + return; + } + catch (const DepListError &) + { + } + } + + Log::get_instance()->message(ll_debug, lc_context, "No resolvable item in || ( ) block. Using " + "first item for error message"); + { + Context block_context("Inside || ( ) block with other options:"); + for (DependencySpecTree::ConstSequenceIterator c(cur) ; c != end ; ++c) + { + if (! is_viable_any_child(*d->_imp->env, d->_imp->current_package_id(), *c)) + continue; + + d->add_not_top_level(*c, destinations, conditions); + return; + } + } +} + +void +DepList::AddVisitor::visit_leaf(const BlockDepSpec & a) +{ + if (dl_blocks_discard_completely == d->_imp->opts->blocks) + return; + + // TODO: check destinations + + Context context("When checking BlockDepSpec '!" + stringify(*a.blocked_spec()) + "':"); + + Save<tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > > save_c( + &conditions, d->_imp->opts->dependency_tags ? ConditionTracker(conditions).add_condition(a) : conditions); + + bool check_whole_list(false); + std::list<MergeList::const_iterator> will_be_installed; + tr1::shared_ptr<const PackageIDSequence> already_installed; + + if (a.blocked_spec()->package_ptr()) + { + PackageDepSpec just_package(tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName( + *a.blocked_spec()->package_ptr()))); + already_installed = d->_imp->env->package_database()->query( + query::SupportsAction<InstalledAction>() & + query::Matches(just_package), + qo_whatever); + + MatchDepListEntryAgainstPackageDepSpec m(d->_imp->env, just_package); + for (std::pair<MergeListIndex::const_iterator, MergeListIndex::const_iterator> p( + d->_imp->merge_list_index.equal_range(*a.blocked_spec()->package_ptr())) ; + p.first != p.second ; ++p.first) + { + if (d->_imp->current_merge_list_entry != d->_imp->merge_list.end()) + { + if (d->_imp->current_merge_list_entry == p.first->second) + continue; + + if (d->_imp->current_merge_list_entry->associated_entry == &*p.first->second) + continue; + } + + if (m(*p.first)) + will_be_installed.push_back(p.first->second); + } + } + else + { + check_whole_list = true; + /* TODO: InstalledAtRoot? */ + already_installed = d->_imp->env->package_database()->query( + query::SupportsAction<InstalledAction>(), + qo_whatever); + } + + if (already_installed->empty() && will_be_installed.empty() && ! check_whole_list) + return; + + for (PackageIDSequence::ConstIterator aa(already_installed->begin()), + aa_end(already_installed->end()) ; aa != aa_end ; ++aa) + { + if (! match_package(*d->_imp->env, *a.blocked_spec(), **aa)) + continue; + + bool replaced(false); + for (std::list<MergeList::const_iterator>::const_iterator r(will_be_installed.begin()), + r_end(will_be_installed.end()) ; r != r_end && ! replaced ; ++r) + if ((*r)->package_id->slot() == (*aa)->slot()) + { + /* if it's a virtual, it only replaces if it's the same package. */ + if ((*r)->package_id->virtual_for_key()) + { + if ((*r)->package_id->virtual_for_key()->value()->name() == (*aa)->name()) + replaced = true; + } + else + replaced = true; + } + + if (replaced) + continue; + + /* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking + * ourself */ + if (! (a.blocked_spec()->version_requirements_ptr() || a.blocked_spec()->slot_ptr() + || a.blocked_spec()->use_requirements_ptr() || a.blocked_spec()->repository_ptr()) + && d->_imp->current_package_id()) + { + if ((*aa)->name() == d->_imp->current_package_id()->name()) + continue; + + if ((*aa)->virtual_for_key() && (*aa)->virtual_for_key()->value()->name() == d->_imp->current_package_id()->name()) + continue; + } + + switch (d->_imp->throw_on_blocker ? dl_blocks_error : d->_imp->opts->blocks) + { + case dl_blocks_error: + throw BlockError(stringify(*a.blocked_spec())); + + case dl_blocks_discard: + Log::get_instance()->message(ll_warning, lc_context, "Discarding block '!" + + stringify(*a.blocked_spec()) + "'"); + break; + + case dl_blocks_discard_completely: + break; + + case dl_blocks_accumulate: + d->add_error_package(*aa, dlk_block, *a.blocked_spec(), conditions); + break; + + case last_dl_blocks: + break; + } + } + + for (std::list<MergeList::const_iterator>::const_iterator r(will_be_installed.begin()), + r_end(will_be_installed.end()) ; r != r_end ; ++r) + { + if (! match_package(*d->_imp->env, *a.blocked_spec(), *(*r)->package_id)) + continue; + + /* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking + * ourself */ + if (! (a.blocked_spec()->version_requirements_ptr() || a.blocked_spec()->slot_ptr() + || a.blocked_spec()->use_requirements_ptr() || a.blocked_spec()->repository_ptr()) + && d->_imp->current_package_id()) + { + if ((*r)->package_id->name() == d->_imp->current_package_id()->name()) + continue; + + if ((*r)->package_id->virtual_for_key() && (*r)->package_id->virtual_for_key()->value()->name() == + d->_imp->current_package_id()->name()) + continue; + } + + throw BlockError(stringify(*a.blocked_spec())); + } + + if (check_whole_list) + { + for (MergeList::const_iterator r(d->_imp->merge_list.begin()), + r_end(d->_imp->merge_list.end()) ; r != r_end ; ++r) + { + if (! match_package(*d->_imp->env, *a.blocked_spec(), *r->package_id)) + continue; + + /* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking + * ourself */ + if (! (a.blocked_spec()->version_requirements_ptr() || a.blocked_spec()->slot_ptr() + || a.blocked_spec()->use_requirements_ptr() || a.blocked_spec()->repository_ptr()) + && d->_imp->current_package_id()) + { + if (r->package_id->name() == d->_imp->current_package_id()->name()) + continue; + + if (r->package_id->virtual_for_key() && + r->package_id->virtual_for_key()->value()->name() == d->_imp->current_package_id()->name()) + continue; + } + + throw BlockError(stringify(*a.blocked_spec())); + } + } +} + +void +DepList::AddVisitor::visit_leaf(const DependencyLabelsDepSpec &) +{ + // XXX implement +} + +DepList::DepList(const Environment * const e, const DepListOptions & o) : + PrivateImplementationPattern<DepList>(new Implementation<DepList>(e, o)) +{ +} + +DepList::~DepList() +{ +} + +tr1::shared_ptr<DepListOptions> +DepList::options() +{ + return _imp->opts; +} + +const tr1::shared_ptr<const DepListOptions> +DepList::options() const +{ + return _imp->opts; +} + +void +DepList::clear() +{ + DepListOptions o(*options()); + _imp.reset(new Implementation<DepList>(_imp->env, o)); +} + +void +DepList::add_in_role(DependencySpecTree::ConstItem & spec, const std::string & role, + tr1::shared_ptr<const DestinationsSet> destinations) +{ + Context context("When adding " + role + ":"); + add_not_top_level(spec, destinations, + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> >( + new ConstTreeSequence<DependencySpecTree, AllDepSpec>(tr1::shared_ptr<AllDepSpec>(new AllDepSpec)))); +} + +void +DepList::add_not_top_level(DependencySpecTree::ConstItem & spec, tr1::shared_ptr<const DestinationsSet> destinations, + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > conditions) +{ + DepListTransaction transaction(_imp->merge_list, _imp->merge_list_index, _imp->merge_list_generation); + + AddVisitor visitor(this, destinations, conditions); + spec.accept(visitor); + transaction.commit(); +} + +void +DepList::add(SetSpecTree::ConstItem & spec, tr1::shared_ptr<const DestinationsSet> destinations) +{ + DepListTransaction transaction(_imp->merge_list, _imp->merge_list_index, _imp->merge_list_generation); + + Save<SetSpecTree::ConstItem *> save_current_top_level_target(&_imp->current_top_level_target, + _imp->current_top_level_target ? _imp->current_top_level_target : &spec); + + AddVisitor visitor(this, destinations); + spec.accept(visitor); + transaction.commit(); +} + +void +DepList::add(const PackageDepSpec & spec, tr1::shared_ptr<const DestinationsSet> destinations) +{ + TreeLeaf<SetSpecTree, PackageDepSpec> l(tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec(spec))); + add(l, destinations); +} + +void +DepList::add_package(const tr1::shared_ptr<const PackageID> & p, tr1::shared_ptr<const DepTag> tag, + const PackageDepSpec & pds, tr1::shared_ptr<DependencySpecTree::ConstItem> conditions, + tr1::shared_ptr<const DestinationsSet> destinations) +{ + Context context("When adding package '" + stringify(*p) + "':"); + + Save<MergeList::iterator> save_merge_list_insert_position(&_imp->merge_list_insert_position); + + /* create our merge list entry. insert pre deps before ourself in the list. insert + * post deps after ourself, and after any provides. */ + + MergeList::iterator our_merge_entry_position( + _imp->merge_list.insert(_imp->merge_list_insert_position, + DepListEntry::create() + .package_id(p) + .generation(_imp->merge_list_generation) + .state(dle_no_deps) + .tags(tr1::shared_ptr<DepListEntryTags>(new DepListEntryTags)) + .destination(p->virtual_for_key() ? tr1::shared_ptr<Repository>() : find_destination(*p, destinations)) + .associated_entry(0) + .handled(p->virtual_for_key() ? + tr1::shared_ptr<DepListEntryHandled>(new DepListEntryNoHandlingRequired) : + tr1::shared_ptr<DepListEntryHandled>(new DepListEntryUnhandled)) + .kind(p->virtual_for_key() ? dlk_virtual : dlk_package))), + our_merge_entry_post_position(our_merge_entry_position); + + _imp->merge_list_index.insert(std::make_pair(p->name(), our_merge_entry_position)); + + if (tag) + our_merge_entry_position->tags->insert(DepTagEntry::create() + .generation(_imp->merge_list_generation) + .tag(tag)); + + if (_imp->opts->dependency_tags && _imp->current_package_id()) + our_merge_entry_position->tags->insert(DepTagEntry::create() + .tag(tr1::shared_ptr<DepTag>(new DependencyDepTag(_imp->current_package_id(), pds, conditions))) + .generation(_imp->merge_list_generation)); + + Save<MergeList::const_iterator> save_current_merge_list_entry(&_imp->current_merge_list_entry, + our_merge_entry_position); + + _imp->merge_list_insert_position = our_merge_entry_position; + + /* add provides */ + if (p->provide_key()) + { + DepSpecFlattener<ProvideSpecTree, PackageDepSpec> f(_imp->env, *_imp->current_package_id()); + p->provide_key()->value()->accept(f); + + if (f.begin() != f.end() && ! DistributionData::get_instance()->distribution_from_string( + _imp->env->default_distribution())->support_old_style_virtuals) + throw DistributionConfigurationError("Package '" + stringify(*p) + "' has PROVIDEs, but this distribution " + "does not support old style virtuals"); + + for (DepSpecFlattener<ProvideSpecTree, PackageDepSpec>::ConstIterator i(f.begin()), i_end(f.end()) ; i != i_end ; ++i) + { + tr1::shared_ptr<VersionRequirements> v(new VersionRequirements); + v->push_back(VersionRequirement(vo_equal, p->version())); + tr1::shared_ptr<PackageDepSpec> pp(new PackageDepSpec( + tr1::shared_ptr<QualifiedPackageName>(new QualifiedPackageName((*i)->text())), + tr1::shared_ptr<CategoryNamePart>(), + tr1::shared_ptr<PackageNamePart>(), + v, vr_and)); + + std::pair<MergeListIndex::iterator, MergeListIndex::iterator> z; + if (pp->package_ptr()) + z = _imp->merge_list_index.equal_range(*pp->package_ptr()); + else + z = std::make_pair(_imp->merge_list_index.begin(), _imp->merge_list_index.end()); + + MergeListIndex::iterator zz(std::find_if(z.first, z.second, + MatchDepListEntryAgainstPackageDepSpec(_imp->env, *pp))); + + if (zz != z.second) + continue; + + our_merge_entry_post_position = _imp->merge_list.insert(next(our_merge_entry_post_position), + DepListEntry(DepListEntry::create() + .package_id(_imp->env->package_database()->fetch_repository( + RepositoryName("virtuals"))->make_virtuals_interface->make_virtual_package_id( + QualifiedPackageName((*i)->text()), p)) + .generation(_imp->merge_list_generation) + .state(dle_has_all_deps) + .tags(tr1::shared_ptr<DepListEntryTags>(new DepListEntryTags)) + .destination(tr1::shared_ptr<Repository>()) + .associated_entry(&*_imp->current_merge_list_entry) + .handled(make_shared_ptr(new DepListEntryNoHandlingRequired)) + .kind(dlk_provided))); + _imp->merge_list_index.insert(std::make_pair((*i)->text(), our_merge_entry_post_position)); + } + } + + /* add suggests */ + if (_imp->opts->suggested == dl_suggested_show && p->suggested_dependencies_key()) + { + Context c("When showing suggestions:"); + Save<MergeList::iterator> suggest_save_merge_list_insert_position(&_imp->merge_list_insert_position, + next(our_merge_entry_position)); + ShowSuggestVisitor visitor(this, destinations, _imp->env, _imp->current_package_id(), _imp->opts->dependency_tags); + p->suggested_dependencies_key()->value()->accept(visitor); + } + + /* add pre dependencies */ + if (p->build_dependencies_key()) + add_predeps(*p->build_dependencies_key()->value(), _imp->opts->uninstalled_deps_pre, "build", destinations); + if (p->run_dependencies_key()) + add_predeps(*p->run_dependencies_key()->value(), _imp->opts->uninstalled_deps_runtime, "run", destinations); + if (p->post_dependencies_key()) + add_predeps(*p->post_dependencies_key()->value(), _imp->opts->uninstalled_deps_post, "post", destinations); + if (_imp->opts->suggested == dl_suggested_install && p->suggested_dependencies_key()) + add_predeps(*p->suggested_dependencies_key()->value(), _imp->opts->uninstalled_deps_suggested, "suggest", destinations); + + our_merge_entry_position->state = dle_has_pre_deps; + _imp->merge_list_insert_position = next(our_merge_entry_post_position); + + /* add post dependencies */ + if (p->build_dependencies_key()) + add_postdeps(*p->build_dependencies_key()->value(), _imp->opts->uninstalled_deps_pre, "build", destinations); + if (p->run_dependencies_key()) + add_postdeps(*p->run_dependencies_key()->value(), _imp->opts->uninstalled_deps_runtime, "run", destinations); + if (p->post_dependencies_key()) + add_postdeps(*p->post_dependencies_key()->value(), _imp->opts->uninstalled_deps_post, "post", destinations); + + if (_imp->opts->suggested == dl_suggested_install && p->suggested_dependencies_key()) + add_postdeps(*p->suggested_dependencies_key()->value(), _imp->opts->uninstalled_deps_suggested, "suggest", destinations); + + our_merge_entry_position->state = dle_has_all_deps; +} + +void +DepList::add_error_package(const tr1::shared_ptr<const PackageID> & p, const DepListEntryKind kind, + const PackageDepSpec & pds, tr1::shared_ptr<DependencySpecTree::ConstItem> conditions) +{ + std::pair<MergeListIndex::iterator, MergeListIndex::const_iterator> pp( + _imp->merge_list_index.equal_range(p->name())); + + for ( ; pp.second != pp.first ; ++pp.first) + { + if (pp.first->second->kind == kind && *pp.first->second->package_id == *p) + { + if (_imp->current_package_id()) + pp.first->second->tags->insert(DepTagEntry::create() + .tag(tr1::shared_ptr<DepTag>(new DependencyDepTag(_imp->current_package_id(), pds, conditions))) + .generation(_imp->merge_list_generation)); + return; + } + } + + MergeList::iterator our_merge_entry_position( + _imp->merge_list.insert(_imp->merge_list.begin(), + DepListEntry::create() + .package_id(p) + .generation(_imp->merge_list_generation) + .state(dle_has_all_deps) + .tags(tr1::shared_ptr<DepListEntryTags>(new DepListEntryTags)) + .destination(tr1::shared_ptr<Repository>()) + .associated_entry(&*_imp->current_merge_list_entry) + .handled(make_shared_ptr(new DepListEntryNoHandlingRequired)) + .kind(kind))); + + if (_imp->current_package_id()) + our_merge_entry_position->tags->insert(DepTagEntry::create() + .tag(tr1::shared_ptr<DepTag>(new DependencyDepTag(_imp->current_package_id(), pds, conditions))) + .generation(_imp->merge_list_generation)); + + _imp->merge_list_index.insert(std::make_pair(p->name(), our_merge_entry_position)); +} + +void +DepList::add_suggested_package(const tr1::shared_ptr<const PackageID> & p, + const PackageDepSpec & pds, tr1::shared_ptr<DependencySpecTree::ConstItem> conditions, + const tr1::shared_ptr<const DestinationsSet> destinations) +{ + std::pair<MergeListIndex::iterator, MergeListIndex::const_iterator> pp( + _imp->merge_list_index.equal_range(p->name())); + + for ( ; pp.second != pp.first ; ++pp.first) + { + if ((pp.first->second->kind == dlk_suggested || pp.first->second->kind == dlk_already_installed + || pp.first->second->kind == dlk_package || pp.first->second->kind == dlk_provided + || pp.first->second->kind == dlk_subpackage) && *pp.first->second->package_id == *p) + return; + } + + MergeList::iterator our_merge_entry_position( + _imp->merge_list.insert(_imp->merge_list_insert_position, + DepListEntry::create() + .package_id(p) + .generation(_imp->merge_list_generation) + .state(dle_has_all_deps) + .tags(tr1::shared_ptr<DepListEntryTags>(new DepListEntryTags)) + .destination(find_destination(*p, destinations)) + .associated_entry(&*_imp->current_merge_list_entry) + .handled(make_shared_ptr(new DepListEntryNoHandlingRequired)) + .kind(dlk_suggested))); + + if (_imp->current_package_id()) + our_merge_entry_position->tags->insert(DepTagEntry::create() + .tag(tr1::shared_ptr<DepTag>(new DependencyDepTag(_imp->current_package_id(), pds, conditions))) + .generation(_imp->merge_list_generation)); + + _imp->merge_list_index.insert(std::make_pair(p->name(), our_merge_entry_position)); +} + +void +DepList::add_predeps(DependencySpecTree::ConstItem & d, const DepListDepsOption opt, const std::string & s, + tr1::shared_ptr<const DestinationsSet> destinations) +{ + if (dl_deps_pre == opt || dl_deps_pre_or_post == opt) + { + try + { + add_in_role(d, s + " dependencies as pre dependencies", destinations); + } + catch (const DepListError & e) + { + if (dl_deps_pre == opt) + throw; + else + Log::get_instance()->message(ll_warning, lc_context, "Dropping " + s + " dependencies to " + "post dependencies because of exception '" + e.message() + "' (" + e.what() + ")"); + } + } +} + +void +DepList::add_postdeps(DependencySpecTree::ConstItem & d, const DepListDepsOption opt, const std::string & s, + tr1::shared_ptr<const DestinationsSet> destinations) +{ + if (dl_deps_pre_or_post == opt || dl_deps_post == opt || dl_deps_try_post == opt) + { + try + { + try + { + add_in_role(d, s + " dependencies as post dependencies", destinations); + } + catch (const CircularDependencyError &) + { + Save<DepListCircularOption> save_circular(&_imp->opts->circular, + _imp->opts->circular == dl_circular_discard_silently ? + dl_circular_discard_silently : dl_circular_discard); + Save<MergeList::iterator> save_merge_list_insert_position(&_imp->merge_list_insert_position, + _imp->merge_list.end()); + add_in_role(d, s + " dependencies as post dependencies with cycle breaking", destinations); + } + } + catch (const DepListError & e) + { + if (dl_deps_try_post != opt) + throw; + else + Log::get_instance()->message(ll_warning, lc_context, "Ignoring " + s + + " dependencies due to exception '" + e.message() + "' (" + e.what() + ")"); + } + } +} + +void +DepList::add_already_installed_package(const tr1::shared_ptr<const PackageID> & p, tr1::shared_ptr<const DepTag> tag, + const PackageDepSpec & pds, tr1::shared_ptr<DependencySpecTree::ConstItem> conditions, + const tr1::shared_ptr<const DestinationsSet> destinations) +{ + Context context("When adding installed package '" + stringify(*p) + "':"); + + Save<MergeList::iterator> save_merge_list_insert_position(&_imp->merge_list_insert_position); + + MergeList::iterator our_merge_entry(_imp->merge_list.insert(_imp->merge_list_insert_position, + DepListEntry::create() + .package_id(p) + .generation(_imp->merge_list_generation) + .tags(tr1::shared_ptr<DepListEntryTags>(new DepListEntryTags)) + .state(dle_has_pre_deps) + .destination(tr1::shared_ptr<Repository>()) + .associated_entry(0) + .handled(make_shared_ptr(new DepListEntryNoHandlingRequired)) + .kind(dlk_already_installed))); + _imp->merge_list_index.insert(std::make_pair(p->name(), our_merge_entry)); + + if (tag) + our_merge_entry->tags->insert(DepTagEntry::create() + .generation(_imp->merge_list_generation) + .tag(tag)); + + if (_imp->opts->dependency_tags && _imp->current_package_id()) + our_merge_entry->tags->insert(DepTagEntry::create() + .tag(tr1::shared_ptr<DepTag>(new DependencyDepTag(_imp->current_package_id(), pds, conditions))) + .generation(_imp->merge_list_generation)); + + Save<MergeList::const_iterator> save_current_merge_list_entry(&_imp->current_merge_list_entry, + our_merge_entry); + + if (p->build_dependencies_key()) + add_predeps(*p->build_dependencies_key()->value(), _imp->opts->installed_deps_pre, "build", destinations); + if (p->run_dependencies_key()) + add_predeps(*p->run_dependencies_key()->value(), _imp->opts->installed_deps_runtime, "run", destinations); + if (p->post_dependencies_key()) + add_predeps(*p->post_dependencies_key()->value(), _imp->opts->installed_deps_post, "post", destinations); + + our_merge_entry->state = dle_has_pre_deps; + _imp->merge_list_insert_position = next(our_merge_entry); + + if (p->build_dependencies_key()) + add_postdeps(*p->build_dependencies_key()->value(), _imp->opts->installed_deps_pre, "build", destinations); + if (p->run_dependencies_key()) + add_postdeps(*p->run_dependencies_key()->value(), _imp->opts->installed_deps_runtime, "run", destinations); + if (p->post_dependencies_key()) + add_postdeps(*p->post_dependencies_key()->value(), _imp->opts->installed_deps_post, "post", destinations); +} + +namespace +{ + bool is_scm(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 +DepList::prefer_installed_over_uninstalled(const PackageID & installed, + const PackageID & uninstalled) +{ + do + { + switch (_imp->opts->target_type) + { + case dl_target_package: + if (! _imp->current_package_id()) + return false; + + if (is_top_level_target(uninstalled)) + return false; + + continue; + + case dl_target_set: + continue; + + case last_dl_target: + ; + } + + throw InternalError(PALUDIS_HERE, "Bad target_type value '" + stringify(_imp->opts->target_type) + "'"); + } while (false); + + if (dl_reinstall_always == _imp->opts->reinstall) + return false; + + if (dl_upgrade_as_needed == _imp->opts->upgrade) + return true; + + if (dl_reinstall_scm_never != _imp->opts->reinstall_scm) + if (uninstalled.version() == installed.version() && + (installed.version().is_scm() || is_scm(installed.name()))) + { + static time_t current_time(time(0)); /* static to avoid weirdness */ + time_t installed_time(current_time); + if (installed.installed_time_key()) + installed_time = installed.installed_time_key()->value(); + + do + { + switch (_imp->opts->reinstall_scm) + { + case dl_reinstall_scm_always: + return false; + + case dl_reinstall_scm_daily: + if (current_time - installed_time > (24 * 60 * 60)) + return false; + continue; + + case dl_reinstall_scm_weekly: + if (current_time - installed_time > (24 * 60 * 60 * 7)) + return false; + continue; + + case dl_reinstall_scm_never: + ; /* nothing */ + + case last_dl_reinstall_scm: + ; + } + + throw InternalError(PALUDIS_HERE, "Bad value for opts->reinstall_scm"); + } while (false); + } + + /* use != rather than > to correctly force a downgrade when packages are + * removed. */ + if (uninstalled.version() != installed.version()) + return false; + + if (dl_reinstall_if_use_changed == _imp->opts->reinstall) + { + std::set<UseFlagName> use_common; + if (installed.iuse_key() && uninstalled.iuse_key()) + std::set_intersection( + installed.iuse_key()->value()->begin(), installed.iuse_key()->value()->end(), + uninstalled.iuse_key()->value()->begin(), uninstalled.iuse_key()->value()->end(), + transform_inserter(std::inserter(use_common, use_common.end()), + paludis::tr1::mem_fn(&IUseFlag::flag))); + + for (std::set<UseFlagName>::const_iterator f(use_common.begin()), f_end(use_common.end()) ; + f != f_end ; ++f) + if (_imp->env->query_use(*f, installed) != _imp->env->query_use(*f, uninstalled)) + return false; + } + + return true; +} + +bool +DepList::already_installed(const DependencySpecTree::ConstItem & spec, + tr1::shared_ptr<const DestinationsSet> destinations) const +{ + QueryVisitor visitor(this, destinations, _imp->env, _imp->current_package_id()); + spec.accept(visitor); + return visitor.result(); +} + +DepList::Iterator +DepList::begin() +{ + return Iterator(_imp->merge_list.begin()); +} + +DepList::Iterator +DepList::end() +{ + return Iterator(_imp->merge_list.end()); +} + +DepList::ConstIterator +DepList::begin() const +{ + return ConstIterator(_imp->merge_list.begin()); +} + +DepList::ConstIterator +DepList::end() const +{ + return ConstIterator(_imp->merge_list.end()); +} + +bool +DepList::is_top_level_target(const PackageID & e) const +{ + if (! _imp->current_top_level_target) + throw InternalError(PALUDIS_HERE, "current_top_level_target not set?"); + + return match_package_in_set(*_imp->env, *_imp->current_top_level_target, e); +} + +namespace +{ + struct IsError + { + bool operator() (const DepListEntry & e) const + { + switch (e.kind) + { + case dlk_virtual: + case dlk_package: + case dlk_provided: + case dlk_already_installed: + case dlk_subpackage: + case dlk_suggested: + return false; + + case dlk_block: + case dlk_masked: + return true; + + case last_dlk: + ; + } + + throw InternalError(PALUDIS_HERE, "Bad e.kind"); + } + }; +} + +bool +DepList::has_errors() const +{ + return end() != std::find_if(begin(), end(), IsError()); +} + +tr1::shared_ptr<Repository> +DepList::find_destination(const PackageID & p, + tr1::shared_ptr<const DestinationsSet> dd) +{ + for (DestinationsSet::ConstIterator d(dd->begin()), d_end(dd->end()) ; + d != d_end ; ++d) + if ((*d)->destination_interface) + if ((*d)->destination_interface->is_suitable_destination_for(p)) + return *d; + + throw NoDestinationError(p, dd); +} + +bool +DepList::replaced(const PackageID & m) const +{ + std::pair<MergeListIndex::const_iterator, MergeListIndex::const_iterator> p( + _imp->merge_list_index.equal_range(m.name())); + + PackageDepSpec spec(make_shared_ptr(new QualifiedPackageName(m.name()))); + while (p.second != ((p.first = std::find_if(p.first, p.second, + MatchDepListEntryAgainstPackageDepSpec(_imp->env, spec))))) + { + if (p.first->second->package_id->slot() != m.slot()) + p.first = next(p.first); + else + return true; + } + + return false; +} + +bool +DepList::match_on_list(const PackageDepSpec & a) const +{ + std::pair<MergeListIndex::const_iterator, MergeListIndex::const_iterator> p; + if (a.package_ptr()) + p = _imp->merge_list_index.equal_range(*a.package_ptr()); + else + p = std::make_pair(_imp->merge_list_index.begin(), _imp->merge_list_index.end()); + + return p.second != std::find_if(p.first, p.second, + MatchDepListEntryAgainstPackageDepSpec(_imp->env, a)); +} + +bool +paludis::is_viable_any_child(const Environment & env, const tr1::shared_ptr<const PackageID> & id, + const DependencySpecTree::ConstItem & i) +{ + const UseDepSpec * const u(get_const_item(i)->as_use_dep_spec()); + if (0 != u) + return (id ? env.query_use(u->flag(), *id) : false) ^ u->inverse(); + else + return true; +} + diff --git a/0.26.0_alpha1/paludis/dep_list.hh b/0.26.0_alpha1/paludis/dep_list.hh new file mode 100644 index 000000000..fb8f6f48e --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_list.hh @@ -0,0 +1,220 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk> + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_PALUDIS_DEP_LIST_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LIST_HH 1 + +#include <paludis/dep_spec-fwd.hh> +#include <paludis/mask-fwd.hh> +#include <paludis/dep_tag.hh> +#include <paludis/dep_list_options.hh> +#include <paludis/dep_list-fwd.hh> +#include <paludis/handled_information-fwd.hh> +#include <paludis/name.hh> +#include <paludis/environment.hh> +#include <paludis/util/instantiation_policy.hh> +#include <paludis/util/private_implementation_pattern.hh> +#include <paludis/util/options.hh> +#include <paludis/util/tr1_functional.hh> +#include <paludis/version_spec.hh> + +#include <iosfwd> + +#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh> + +/** \file + * Declarations for DepList and related classes. + * + * \ingroup g_dep_list + * + * \section Examples + * + * - None at this time. Use InstallTask if you need to install things. + */ + +namespace paludis +{ + /** + * A sequence of functions to try, in order, when overriding masks. + * + * \ingroup g_dep_list + */ + typedef Sequence<tr1::function<bool (const PackageID &, const Mask &)> > DepListOverrideMasksFunctions; + +#include <paludis/dep_list-sr.hh> + + /** + * Holds a list of dependencies in merge order. + * + * \ingroup g_dep_list + * \nosubgrouping + */ + class PALUDIS_VISIBLE DepList : + private InstantiationPolicy<DepList, instantiation_method::NonCopyableTag>, + private PrivateImplementationPattern<DepList> + { + protected: + class AddVisitor; + friend class AddVisitor; + + /** + * Find an appropriate destination for a package. + */ + tr1::shared_ptr<Repository> find_destination(const PackageID &, + tr1::shared_ptr<const DestinationsSet>); + + /** + * Add a DepSpec with role context. + */ + void add_in_role(DependencySpecTree::ConstItem &, const std::string & role, + tr1::shared_ptr<const DestinationsSet>); + + /** + * Return whether we prefer the first parameter, which is installed, + * over the second, which isn't. + */ + bool prefer_installed_over_uninstalled(const PackageID &, + const PackageID &); + + /** + * Add a package to the list. + */ + void add_package(const tr1::shared_ptr<const PackageID> &, tr1::shared_ptr<const DepTag>, + const PackageDepSpec &, tr1::shared_ptr<DependencySpecTree::ConstItem>, + tr1::shared_ptr<const DestinationsSet> destinations); + + /** + * Add an already installed package to the list. + */ + void add_already_installed_package(const tr1::shared_ptr<const PackageID> &, tr1::shared_ptr<const DepTag>, + const PackageDepSpec &, tr1::shared_ptr<DependencySpecTree::ConstItem>, + tr1::shared_ptr<const DestinationsSet> destinations); + + /** + * Add an error package to the list. + */ + void add_error_package(const tr1::shared_ptr<const PackageID> &, const DepListEntryKind, + const PackageDepSpec &, tr1::shared_ptr<DependencySpecTree::ConstItem>); + + /** + * Add predependencies. + */ + void add_predeps(DependencySpecTree::ConstItem &, const DepListDepsOption, const std::string &, + tr1::shared_ptr<const DestinationsSet> destinations); + + /** + * Add postdependencies. + */ + void add_postdeps(DependencySpecTree::ConstItem &, const DepListDepsOption, const std::string &, + tr1::shared_ptr<const DestinationsSet> destinations); + + /** + * Return whether the specified PackageID is matched by + * the top level target. + */ + bool is_top_level_target(const PackageID &) const; + + void add_not_top_level(DependencySpecTree::ConstItem &, + tr1::shared_ptr<const DestinationsSet> target_destinations, + tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > conditions); + + public: + ///\name Basic operations + ///\{ + + DepList(const Environment * const, const DepListOptions &); + + virtual ~DepList(); + + ///\} + + /** + * Our options. + */ + tr1::shared_ptr<DepListOptions> options(); + + /** + * Our options. + */ + const tr1::shared_ptr<const DepListOptions> options() const; + + /** + * Add the packages required to resolve an additional dependency + * spec. + */ + void add(SetSpecTree::ConstItem &, + tr1::shared_ptr<const DestinationsSet> target_destinations); + + /** + * Add the packages required to resolve an additional dependency + * spec. + */ + void add(const PackageDepSpec &, + tr1::shared_ptr<const DestinationsSet> target_destinations); + + /** + * Clear the list. + */ + void clear(); + + /** + * Return whether a spec structure is already installed. + */ + bool already_installed(DependencySpecTree::ConstItem &, + tr1::shared_ptr<const DestinationsSet> target_destinations) const; + + /** + * Return whether a PackageID has been replaced. + */ + bool replaced(const PackageID &) const; + + /** + * Return whether a spec matches an item in the list. + */ + bool match_on_list(const PackageDepSpec &) const; + + /** + * Whether we have any errors. + */ + bool has_errors() const; + + /** + * Add a suggested package to the list. + */ + void add_suggested_package(const tr1::shared_ptr<const PackageID> &, + const PackageDepSpec &, tr1::shared_ptr<DependencySpecTree::ConstItem>, + tr1::shared_ptr<const DestinationsSet> destinations); + + ///\name Iterate over our dependency list entries. + ///\{ + + typedef libwrapiter::ForwardIterator<DepList, DepListEntry> Iterator; + typedef libwrapiter::ForwardIterator<DepList, const DepListEntry> ConstIterator; + + Iterator begin(); + Iterator end(); + + ConstIterator begin() const; + ConstIterator end() const; + + ///\} + }; +} + +#endif diff --git a/0.26.0_alpha1/paludis/dep_list.sr b/0.26.0_alpha1/paludis/dep_list.sr new file mode 100644 index 000000000..dafbfe81f --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_list.sr @@ -0,0 +1,78 @@ +#!/bin/bash +# vim: set sw=4 sts=4 et : + +make_class_DepListOptions() +{ + visible + + key reinstall DepListReinstallOption + key reinstall_scm DepListReinstallScmOption + key target_type DepListTargetType + key upgrade DepListUpgradeOption + key downgrade DepListDowngradeOption + key new_slots DepListNewSlotsOption + key fall_back DepListFallBackOption + + key installed_deps_pre DepListDepsOption + key installed_deps_runtime DepListDepsOption + key installed_deps_post DepListDepsOption + + key uninstalled_deps_pre DepListDepsOption + key uninstalled_deps_runtime DepListDepsOption + key uninstalled_deps_post DepListDepsOption + key uninstalled_deps_suggested DepListDepsOption + + key suggested DepListSuggestedOption + key circular DepListCircularOption + key use DepListUseOption + key blocks DepListBlocksOption + key override_masks "tr1::shared_ptr<DepListOverrideMasksFunctions>" + + key dependency_tags bool + + extra_constructors <<END + DepListOptions(); +END + + allow_named_args + + doxygen_comment << "END" + /** + * Parameters for a DepList. + * + * \see DepList + * \ingroup g_dep_list + * \nosubgrouping + */ +END +} + +make_class_DepListEntry() +{ + visible + + key kind DepListEntryKind + + key package_id "tr1::shared_ptr<const PackageID>" + key associated_entry "const DepListEntry *" + key tags "tr1::shared_ptr<DepListEntryTags>" + key destination "tr1::shared_ptr<Repository>" + + key generation long + key state DepListEntryState + + key handled "tr1::shared_ptr<const DepListEntryHandled>" + + allow_named_args + + doxygen_comment << "END" + /** + * An entry in a DepList. + * + * \see DepList + * \ingroup g_dep_list + * \nosubgrouping + */ +END +} + diff --git a/0.26.0_alpha1/paludis/dep_list_TEST.cc b/0.26.0_alpha1/paludis/dep_list_TEST.cc new file mode 100644 index 000000000..e69f0ffa5 --- /dev/null +++ b/0.26.0_alpha1/paludis/dep_list_TEST.cc @@ -0,0 +1,1802 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006, 2007 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 "dep_list_TEST.hh" +#include <paludis/util/visitor-impl.hh> +#include <paludis/util/set.hh> +#include <paludis/package_id.hh> +#include <paludis/mask.hh> +#include <paludis/stringify_formatter-impl.hh> +#include <paludis/repositories/fake/fake_package_id.hh> +#include <paludis/override_functions.hh> +#include <paludis/repositories/e/dep_spec_pretty_printer.hh> +#include <libwrapiter/libwrapiter_forward_iterator.hh> +#include <libwrapiter/libwrapiter_output_iterator.hh> + +using namespace paludis; +using namespace test; + +namespace test_cases +{ + /** + * Convenience sub base class used by the numbered DepList tests. + * + */ + template <int i_> + struct DepListTestCase : DepListTestCaseBase + { + /** + * Constructor. + */ + DepListTestCase() : + DepListTestCaseBase("dep list " + stringify(i_)) + { + } + }; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase1 : DepListTestCase<1> + { + void populate_repo() + { + repo->add_version("cat", "one", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_1; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase2 : DepListTestCase<2> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_2; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase3 : DepListTestCase<3> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/three"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_3; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase4 : DepListTestCase<4> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_4; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase5 : DepListTestCase<5> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/three"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_5; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase6 : DepListTestCase<6> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/two"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_6; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase7 : DepListTestCase<7> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "four", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/four-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_7; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase8 : DepListTestCase<8> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/four cat/three"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "four", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/four-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_8; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase9 : DepListTestCase<9> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/four cat/two"); + repo->add_version("cat", "four", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/four-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_9; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase10 : DepListTestCase<10> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_10; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase11 : DepListTestCase<11> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/four )"); + repo->add_version("cat", "four", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_11; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase12 : DepListTestCase<12> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( ( cat/two cat/three ) cat/four )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + repo->add_version("cat", "four", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_12; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase13 : DepListTestCase<13> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three cat/four"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + repo->add_version("cat", "four", "1")->build_dependencies_key()->set_from_string("|| ( ( cat/two cat/three ) cat/five )"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/four-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_13; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase14 : DepListTestCase<14> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/three )"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_14; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase15 : DepListTestCase<15> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/three )"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_15; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase16 : DepListTestCase<16> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two:slot2"); + repo->add_version("cat", "two", "1.1")->set_slot(SlotName("slot1")); + repo->add_version("cat", "two", "1.2")->set_slot(SlotName("slot2")); + repo->add_version("cat", "two", "1.3")->set_slot(SlotName("slot3")); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1.2:slot2::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_16; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase17 : DepListTestCase<17> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("<cat/two-1.2-r2:slot2"); + repo->add_version("cat", "two", "1.1")->set_slot(SlotName("slot1")); + repo->add_version("cat", "two", "1.2")->set_slot(SlotName("slot2")); + repo->add_version("cat", "two", "1.2-r1")->set_slot(SlotName("slot2")); + repo->add_version("cat", "two", "1.2-r2")->set_slot(SlotName("slot2")); + repo->add_version("cat", "two", "1.3")->set_slot(SlotName("slot3")); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1.2-r1:slot2::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_17; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase18 : DepListTestCase<18> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( )"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_18; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase19 : DepListTestCase<19> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("enabled? ( cat/two )"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_19; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase20 : DepListTestCase<20> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("!enabled? ( cat/two )"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_20; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase21 : DepListTestCase<21> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("disabled? ( cat/two )"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_21; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase22 : DepListTestCase<22> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("!disabled? ( cat/two )"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_22; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase23 : DepListTestCase<23> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( enabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_23; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase24 : DepListTestCase<24> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( !enabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_24; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase25 : DepListTestCase<25> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( disabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_25; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase26 : DepListTestCase<26> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( !disabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_26; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase27 : DepListTestCase<27> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( enabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_27; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase28 : DepListTestCase<28> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( !enabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_28; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase29 : DepListTestCase<29> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( disabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_29; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase30 : DepListTestCase<30> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( !disabled? ( cat/two ) cat/three )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_30; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase31 : DepListTestCase<31> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( enabled? ( cat/three ) cat/two )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_31; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase32 : DepListTestCase<32> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( !enabled? ( cat/three ) cat/two )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_32; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase33 : DepListTestCase<33> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( disabled? ( cat/three ) cat/two )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_33; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase34 : DepListTestCase<34> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/three || ( !disabled? ( cat/three ) cat/two )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_34; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase35 : DepListTestCase<35> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( enabled1? ( cat/two ) enabled2? ( cat/three ) )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_35; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase36 : DepListTestCase<36> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( !enabled1? ( cat/two ) enabled2? ( cat/three ) )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_36; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase37 : DepListTestCase<37> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( !enabled1? ( cat/two ) !enabled2? ( cat/three ) )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_37; + + struct DepListTestCase38 : DepListTestCase<38> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->keywords_key()->set_from_string("test"); + repo->add_version("cat", "one", "2")->keywords_key()->set_from_string("~test"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_38; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase42 : DepListTestCase<42> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/three )"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/one"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_42; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase43 : DepListTestCase<43> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/three )"); + repo->add_version("cat", "two", "1")->post_dependencies_key()->set_from_string("cat/one"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_43; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase44 : DepListTestCase<44> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two cat/two )"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_44; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase45 : DepListTestCase<45> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two[enabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_45; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase46 : DepListTestCase<46> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two[-disabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_46; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase47 : DepListTestCase<47> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two[disabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + } + + void check_lists() + { + TEST_CHECK(true); + DepList d(&env, DepListOptions()); + TEST_CHECK_THROWS(d.add(PackageDepSpec(merge_target, pds_pm_permissive), + env.default_destinations()), DepListError); + TEST_CHECK(d.begin() == d.end()); + } + } test_dep_list_47; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase48 : DepListTestCase<48> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two[-enabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + } + + void check_lists() + { + TEST_CHECK(true); + DepList d(&env, DepListOptions()); + TEST_CHECK_THROWS(d.add(PackageDepSpec(merge_target, pds_pm_permissive), + env.default_destinations()), DepListError); + TEST_CHECK(d.begin() == d.end()); + } + } test_dep_list_48; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase49 : DepListTestCase<49> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two cat/two[enabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_49; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase50 : DepListTestCase<50> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two cat/two[-disabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_50; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase51 : DepListTestCase<51> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two cat/two[disabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + } + + void check_lists() + { + TEST_CHECK(true); + DepList d(&env, DepListOptions()); + TEST_CHECK_THROWS(d.add(PackageDepSpec(merge_target, pds_pm_permissive), + env.default_destinations()), DepListError); + TEST_CHECK(d.begin() == d.end()); + } + } test_dep_list_51; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase52 : DepListTestCase<52> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("( cat/two cat/two[-enabled] )"); + repo->add_version("cat", "two", "1")->iuse_key()->set_from_string("ebuild", iuse_pm_permissive); + } + + void populate_expected() + { + merge_target = "cat/one"; + } + + void check_lists() + { + TEST_CHECK(true); + DepList d(&env, DepListOptions()); + TEST_CHECK_THROWS(d.add(PackageDepSpec(merge_target, pds_pm_permissive), + env.default_destinations()), DepListError); + TEST_CHECK(d.begin() == d.end()); + } + } test_dep_list_52; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase53 : DepListTestCase<53> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->post_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + } + } test_dep_list_53; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase54 : DepListTestCase<54> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->post_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/three"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + } + } test_dep_list_54; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase55 : DepListTestCase<55> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->post_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/one"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + } + } test_dep_list_55; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase56 : DepListTestCase<56> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two || ( cat/three virtual/four )"); + repo->add_version("cat", "two", "1")->provide_key()->set_from_string("virtual/four"); + repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("virtual/four-1::virtuals (virtual for cat/two-1:0::repo)"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_56; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase57 : DepListTestCase<57> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->post_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/three"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/one"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + expected.push_back("cat/three-1:0::repo"); + expected.push_back("cat/two-1:0::repo"); + } + } test_dep_list_57; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase58 : DepListTestCase<58> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->provide_key()->set_from_string("virtual/two"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/one-1:0::repo"); + expected.push_back("virtual/two-1::virtuals (virtual for cat/one-1:0::repo)"); + } + } test_dep_list_58; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase59 : DepListTestCase<59> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two >=cat/three-2 )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "2"); + installed_repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/three-2:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_59; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase60 : DepListTestCase<60> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two >=cat/three-3 )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "three", "2"); + installed_repo->add_version("cat", "three", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_60; + + struct DepListTestCase61 : DepListTestCase<61> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->provide_key()->set_from_string("virtual/foo"); + tr1::shared_ptr<FakePackageID> m(repo->add_version("cat", "two", "2")); + m->provide_key()->set_from_string("virtual/foo"); + m->build_dependencies_key()->set_from_string("cat/one"); + } + + void populate_expected() + { + merge_target = "cat/two"; + expected.push_back("cat/one-1:0::repo"); + expected.push_back("virtual/foo-1::virtuals (virtual for cat/one-1:0::repo)"); + expected.push_back("cat/two-2:0::repo"); + expected.push_back("virtual/foo-2::virtuals (virtual for cat/two-2:0::repo)"); + } + } test_dep_list_61; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase62 : DepListTestCase<62> + { + void set_options(DepListOptions & opts) + { + using namespace tr1::placeholders; + opts.override_masks.reset(new DepListOverrideMasksFunctions); + opts.override_masks->push_back(tr1::bind(&override_tilde_keywords, &env, _1, _2)); + } + + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( cat/two cat/three )"); + repo->add_version("cat", "two", "1")->keywords_key()->set_from_string("~test"); + repo->add_version("cat", "three", "2")->keywords_key()->set_from_string("~test"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo(M)"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_62; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase63 : DepListTestCase<63> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( =cat/two-1 =cat/two-2 )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "two", "2"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-2:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_63; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase64 : DepListTestCase<64> + { + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( =cat/two-1 =cat/two-2 )"); + repo->add_version("cat", "two", "1"); + repo->add_version("cat", "two", "2"); + installed_repo->add_version("cat", "two", "1"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-2:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_64; + + /** + * \test Test DepList resolution behaviour. + * + */ + struct DepListTestCase65 : DepListTestCase<65> + { + void set_options(DepListOptions & opts) + { + using namespace tr1::placeholders; + opts.override_masks.reset(new DepListOverrideMasksFunctions); + opts.override_masks->push_back(tr1::bind(&override_tilde_keywords, &env, _1, _2)); + } + + void populate_repo() + { + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("|| ( =cat/two-2 =cat/two-1 )"); + repo->add_version("cat", "two", "1")->keywords_key()->set_from_string("~test"); + } + + void populate_expected() + { + merge_target = "cat/one"; + expected.push_back("cat/two-1:0::repo(M)"); + expected.push_back("cat/two-1:0::repo"); + expected.push_back("cat/one-1:0::repo"); + } + } test_dep_list_65; + + /** + * \test Test DepList transactional add behaviour. + * + */ + struct DepListTestCaseTransactionalAdd : TestCase + { + DepListTestCaseTransactionalAdd() : TestCase("dep list transactional add") { } + + void run() + { + TestEnvironment env; + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + tr1::shared_ptr<FakeInstalledRepository> destination_repo(new FakeInstalledRepository(&env, + RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, destination_repo); + + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/four cat/two"); + repo->add_version("cat", "four", "1"); + repo->add_version("cat", "five", "1")->build_dependencies_key()->set_from_string("cat/six cat/seven"); + repo->add_version("cat", "six", "1"); + repo->add_version("cat", "seven", "1")->build_dependencies_key()->set_from_string("cat/doesnotexist"); + + DepList d(&env, DepListOptions()); + d.add(PackageDepSpec("cat/one", pds_pm_permissive), env.default_destinations()); + TEST_CHECK_EQUAL(join(d.begin(), d.end(), " "), + "cat/four-1:0::repo cat/two-1:0::repo cat/three-1:0::repo cat/one-1:0::repo"); + + TEST_CHECK_THROWS(d.add(PackageDepSpec("cat/five", pds_pm_permissive), + env.default_destinations()), DepListError); + + TEST_CHECK_EQUAL(join(d.begin(), d.end(), " "), + "cat/four-1:0::repo cat/two-1:0::repo cat/three-1:0::repo cat/one-1:0::repo"); + } + } test_dep_list_transactional_add; + + /** + * \test Test DepList transactional add behaviour on PDEPENDs. + * + */ + struct DepListTestCaseTransactionalAddPost : TestCase + { + DepListTestCaseTransactionalAddPost() : TestCase("dep list transactional add post") { } + + void run() + { + TestEnvironment env; + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + tr1::shared_ptr<FakeInstalledRepository> destination_repo(new FakeInstalledRepository(&env, + RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, destination_repo); + + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two cat/three"); + repo->add_version("cat", "two", "1")->build_dependencies_key()->set_from_string("cat/four"); + repo->add_version("cat", "three", "1")->build_dependencies_key()->set_from_string("cat/four cat/two"); + repo->add_version("cat", "four", "1"); + repo->add_version("cat", "five", "1")->build_dependencies_key()->set_from_string("cat/six cat/seven"); + repo->add_version("cat", "six", "1"); + repo->add_version("cat", "seven", "1")->post_dependencies_key()->set_from_string("cat/doesnotexist"); + + DepList d(&env, DepListOptions()); + d.add(PackageDepSpec("cat/one", pds_pm_permissive), env.default_destinations()); + TEST_CHECK_EQUAL(join(d.begin(), d.end(), " "), + "cat/four-1:0::repo cat/two-1:0::repo cat/three-1:0::repo cat/one-1:0::repo"); + + TEST_CHECK_THROWS(d.add(PackageDepSpec("cat/five", pds_pm_permissive), + env.default_destinations()), DepListError); + + TEST_CHECK_EQUAL(join(d.begin(), d.end(), " "), + "cat/four-1:0::repo cat/two-1:0::repo cat/three-1:0::repo cat/one-1:0::repo"); + } + } test_dep_list_transactional_add_post; + + /** + * \test Test DepList transactional forced downgrade of installed package behaviour. + * + */ + struct DepListTestCaseForcedDowngradeOfInstalled : TestCase + { + DepListTestCaseForcedDowngradeOfInstalled() : TestCase("dep list forced downgrade of installed") { } + + void run() + { + TestEnvironment env; + + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + repo->add_version("cat", "one", "1"); + + tr1::shared_ptr<FakeInstalledRepository> installed_repo( + new FakeInstalledRepository(&env, RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, installed_repo); + installed_repo->add_version("cat", "one", "2"); + + DepList d(&env, DepListOptions()); + d.add(PackageDepSpec("cat/one", pds_pm_permissive), env.default_destinations()); + TEST_CHECK_EQUAL(join(d.begin(), d.end(), " "), "cat/one-1:0::repo"); + } + } test_dep_list_forced_downgrade_of_installed; + + /** + * \test Test DepList fall back never. + */ + struct DepListTestCaseFallBackNever : TestCase + { + DepListTestCaseFallBackNever() : TestCase("dep list fall back never") { } + + void run() + { + TestEnvironment env; + + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two"); + + tr1::shared_ptr<FakeInstalledRepository> installed_repo( + new FakeInstalledRepository(&env, RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, installed_repo); + installed_repo->add_version("cat", "two", "2"); + + DepList d(&env, DepListOptions()); + d.options()->fall_back = dl_fall_back_never; + TEST_CHECK_THROWS(d.add(PackageDepSpec("cat/one", pds_pm_permissive), + env.default_destinations()), DepListError); + } + } test_dep_list_fall_back_never; + + /** + * \test Test DepList fall back as needed. + */ + struct DepListTestCaseFallBackAsNeeded : TestCase + { + DepListTestCaseFallBackAsNeeded() : TestCase("dep list fall back as needed") { } + + void run() + { + TestEnvironment env; + + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two"); + + tr1::shared_ptr<FakeInstalledRepository> installed_repo( + new FakeInstalledRepository(&env, RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, installed_repo); + installed_repo->add_version("cat", "two", "2"); + + DepList d(&env, DepListOptions()); + d.options()->fall_back = dl_fall_back_as_needed; + d.add(PackageDepSpec("cat/one", pds_pm_permissive), env.default_destinations()); + d.add(PackageDepSpec("cat/two", pds_pm_permissive), env.default_destinations()); + TEST_CHECK_EQUAL(join(d.begin(), d.end(), " "), "cat/two-2:0::installed_repo cat/one-1:0::repo"); + } + } test_dep_list_fall_back_as_needed; + + /** + * \test Test DepList fall back as needed. + */ + struct DepListTestCaseFallBackAsNeededNotTargets : TestCase + { + DepListTestCaseFallBackAsNeededNotTargets() : TestCase("dep list fall back as needed not targets") { } + + void run() + { + TestEnvironment env; + + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two"); + + tr1::shared_ptr<FakeInstalledRepository> installed_repo( + new FakeInstalledRepository(&env, RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, installed_repo); + installed_repo->add_version("cat", "two", "2"); + installed_repo->add_version("cat", "three", "3"); + + DepList d1(&env, DepListOptions()); + d1.options()->fall_back = dl_fall_back_as_needed_except_targets; + d1.add(PackageDepSpec("cat/one", pds_pm_permissive), env.default_destinations()); + TEST_CHECK_EQUAL(join(d1.begin(), d1.end(), " "), "cat/two-2:0::installed_repo cat/one-1:0::repo"); + TEST_CHECK_THROWS(d1.add(PackageDepSpec("cat/three", pds_pm_permissive), + env.default_destinations()), DepListError); + + DepList d2(&env, DepListOptions()); + d2.options()->fall_back = dl_fall_back_as_needed_except_targets; + TEST_CHECK_THROWS(d2.add(PackageDepSpec("cat/two", pds_pm_permissive), + env.default_destinations()), DepListError); + + DepList d3(&env, DepListOptions()); + d3.options()->fall_back = dl_fall_back_as_needed_except_targets; + tr1::shared_ptr<ConstTreeSequence<SetSpecTree, AllDepSpec> > t3(new ConstTreeSequence<SetSpecTree, AllDepSpec>( + tr1::shared_ptr<AllDepSpec>(new AllDepSpec))); + t3->add(tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> >(new TreeLeaf<SetSpecTree, PackageDepSpec>( + tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec("cat/one", pds_pm_permissive))))); + t3->add(tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> >(new TreeLeaf<SetSpecTree, PackageDepSpec>( + tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec("cat/two", pds_pm_permissive))))); + TEST_CHECK_THROWS(d3.add(*t3, env.default_destinations()), DepListError); + + DepList d4(&env, DepListOptions()); + tr1::shared_ptr<ConstTreeSequence<SetSpecTree, AllDepSpec> > t4(new ConstTreeSequence<SetSpecTree, AllDepSpec>( + tr1::shared_ptr<AllDepSpec>(new AllDepSpec))); + t4->add(tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> >(new TreeLeaf<SetSpecTree, PackageDepSpec>( + tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec("cat/one", pds_pm_permissive))))); + t4->add(tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> >(new TreeLeaf<SetSpecTree, PackageDepSpec>( + tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec("cat/three", pds_pm_permissive))))); + TEST_CHECK_THROWS(d4.add(*t4, env.default_destinations()), DepListError); + } + } test_dep_list_fall_back_as_needed_not_targets; + + /** + * \test Test DepList upgrade as needed. + */ + struct DepListTestCaseUpgradeAsNeeded : TestCase + { + DepListTestCaseUpgradeAsNeeded() : TestCase("dep list upgrade as needed") { } + + void run() + { + TestEnvironment env; + + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + repo->add_version("cat", "one", "1")->build_dependencies_key()->set_from_string("cat/two"); + repo->add_version("cat", "two", "2"); + + tr1::shared_ptr<FakeInstalledRepository> installed_repo( + new FakeInstalledRepository(&env, RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, installed_repo); + installed_repo->add_version("cat", "two", "0"); + + DepList d1(&env, DepListOptions()); + d1.options()->upgrade = dl_upgrade_as_needed; + d1.add(PackageDepSpec("cat/one", pds_pm_permissive), env.default_destinations()); + TEST_CHECK_EQUAL(join(d1.begin(), d1.end(), " "), "cat/two-0:0::installed_repo cat/one-1:0::repo"); + + DepList d2(&env, DepListOptions()); + d2.options()->upgrade = dl_upgrade_as_needed; + + tr1::shared_ptr<ConstTreeSequence<SetSpecTree, AllDepSpec> > t2(new ConstTreeSequence<SetSpecTree, AllDepSpec>( + tr1::shared_ptr<AllDepSpec>(new AllDepSpec))); + t2->add(tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> >(new TreeLeaf<SetSpecTree, PackageDepSpec>( + tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec("cat/one", pds_pm_permissive))))); + t2->add(tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> >(new TreeLeaf<SetSpecTree, PackageDepSpec>( + tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec("cat/two", pds_pm_permissive))))); + d2.add(*t2, env.default_destinations()); + TEST_CHECK_EQUAL(join(d2.begin(), d2.end(), " "), "cat/two-2:0::repo cat/one-1:0::repo"); + } + } test_dep_list_upgrade_as_needed; + + /** + * \test Test DepList reinstall scm. + */ + struct DepListTestCaseReinstallSCM : TestCase + { + DepListTestCaseReinstallSCM() : TestCase("dep list reinstall scm") { } + + void run() + { + TestEnvironment env; + + tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo"))); + env.package_database()->add_repository(1, repo); + repo->add_version("cat", "zero", "1")->build_dependencies_key()->set_from_string( + "( cat/one cat/two cat/three-live cat/four-cvs cat/five-svn cat/six-darcs )"); + repo->add_version("cat", "one", "scm"); + repo->add_version("cat", "two", "2"); + repo->add_version("cat", "three-live", "0"); + repo->add_version("cat", "four-cvs", "0"); + repo->add_version("cat", "five-svn", "0"); + repo->add_version("cat", "six-darcs", "0"); + + tr1::shared_ptr<FakeInstalledRepository> installed_repo( + new FakeInstalledRepository(&env, RepositoryName("installed_repo"))); + env.package_database()->add_repository(2, installed_repo); + installed_repo->add_version("cat", "one", "scm"); + installed_repo->add_version("cat", "two", "2"); + installed_repo->add_version("cat", "three-live", "0"); + installed_repo->add_version("cat", "four-cvs", "0"); + installed_r |