diff options
322 files changed, 24695 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..9a50aa371 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +Authors of Paludis +================== + +Ciaran McCreesh <ciaranm@gentoo.org> + Main code + +Stephen P. Bennet <spb@gentoo.org> + Contributor + +Marc Loeser <halcy0n@gentoo.org> + Contributor + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..5b2565fda --- /dev/null +++ b/Makefile.am @@ -0,0 +1,12 @@ +CLEANFILES = *~ +MAINTAINERCLEANFILES = Makefile.in configure config/* aclocal.m4 \ + config.h config.h.in INSTALL COPYING +AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip +EXTRA_DIST = autogen.bash +SUBDIRS = misc test paludis src doc + +doxygen : + $(MAKE) -C doc doxygen + + + @@ -0,0 +1,3 @@ +News for Paludis +================ + @@ -0,0 +1,14 @@ +README for Paludis +================== + +Paludis is in the really early prototype not intended for real use stage. If you +aren't comfortable with C++, ebuild internals and Gentoo in general then you +shouldn't be touching it. + +Developer documentation is available via 'make doxygen' (you need Doxygen +installed, and having GraphViz will help too). It will be created under +'doc/html/'. User documentation is kept in the bottom of a locked filing cabinet +stuck in a disused lavatory with a sign on the door saying 'Beware of the +Leopard'. + +.. vim: set spell spelllang=en tw=80 : .. diff --git a/autogen.bash b/autogen.bash new file mode 100755 index 000000000..e9ecfac5d --- /dev/null +++ b/autogen.bash @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# vim: set sw=4 sts=4 et tw=80 : + +if test "xyes" = x"${BASH_VERSION}" ; then + echo "This is not bash!" + exit 127 +fi + +trap 'echo "exiting." ; exit 250' 15 +KILL_PID=$$ + +run() { + echo ">>> $@" 1>&2 + if ! $@ ; then + echo "oops!" 1>&2 + exit 127 + fi +} + +make_from_m4() { + echo ">>> $(get_m4 ) -E ${1}.m4 > ${1}" + if ! $(get_m4 ) -E ${1}.m4 > ${1} ; then + echo "oops!" 1>&2 + exit 127 + fi +} + +get() { + type ${1}-${2} &>/dev/null && echo ${1}-${2} && return + type ${1}${2//.} &>/dev/null && echo ${1}${2//.} && return + type ${1} &>/dev/null && echo ${1} && return + echo "Could not find ${1} ${2}" 1>&2 + kill $KILL_PID +} + +get_m4() { + type "gm4" &>/dev/null && echo gm4 && return + type "m4" &>/dev/null && echo m4 && return + echo "Could not find m4" 1>&2 + kill $KILL_PID +} + +make_from_m4 paludis/Makefile.am +make_from_m4 paludis/paludis.hh +make_from_m4 paludis/smart_record.hh +make_from_m4 paludis/comparison_policy.hh +run mkdir -p config +run $(get libtoolize 1.5 ) --copy --force --automake +rm -f config.cache +run $(get aclocal 1.9 ) +run $(get autoheader 2.59 ) +run $(get autoconf 2.59 ) +run $(get automake 1.9 ) -a --copy + diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..a8ed448eb --- /dev/null +++ b/configure.ac @@ -0,0 +1,202 @@ +dnl vim: set sw=4 sts=4 ts=4 noet ft=config foldmethod=marker foldmarker={{{,}}} : + +dnl {{{ program, version +AC_PREREQ(2.59) +AC_INIT([paludis/paludis.hh]) +AC_CONFIG_AUX_DIR(config) + +VERSION_MAJOR=0 +VERSION_MINOR=1 +VERSION_MICRO=0 +VERSION_FULL="$VERSION_MAJOR.$VERSION_MINOR.$VERSION_MICRO" +VERSION="$VERSION_FULL" + +AC_SUBST([VERSION_MAJOR]) +AC_SUBST([VERSION_MINOR]) +AC_SUBST([VERSION_MICRO]) +AC_SUBST([VERSION_FULL]) + +AM_INIT_AUTOMAKE(paludis, [$VERSION_FULL]) +dnl }}} + +dnl {{{ basic toolchain checks +AC_LANG([C++]) +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_RANLIB +AC_PROG_MAKE_SET +dnl }}} + +dnl {{{ check for basic_string and string::find_last_not_of +AC_MSG_CHECKING([for a sufficiently standard std::basic_string<>]) +AC_COMPILE_IFELSE([ +#include <string> +int main(int, char **) +{ + std::string s("test"); + std::basic_string<int> t; + return std::string::npos != s.find_last_not_of("abcde") ? 0 : 1; +} +], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + AC_MSG_ERROR([I need a less broken std::basic_string<> implementation]) + ]) +dnl }}} + +dnl {{{ check for limits +AC_MSG_CHECKING([for a usable std::numeric_limits]) +AC_COMPILE_IFELSE([ +#include <limits> +int main(int, char **) +{ + return std::numeric_limits<unsigned>::digits >> 3; +} +], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + AC_MSG_ERROR([Your std::numeric_limits either doesn't exist or hates me]) + ]) +dnl }}} + +dnl {{{ we need libebt. +dnl don't use AC_CHECK_HEADER, it does silly things +AC_MSG_CHECKING([for libebt]) +AC_COMPILE_IFELSE([ +#include <libebt/libebt.hh> +#include <string> +struct Tag { }; +int main(int, char **) +{ + libebt::BacktraceContext<Tag> context("blah"); +} +], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([libebt (http://libebt.berlios.de/) is required])]) +dnl }}} + +dnl {{{ check for various misc functions. +dnl It's probably possible to make many of these optional rather than +dnl hard requirements. If any of these fail for you, send patches. +AC_CHECK_FUNCS([alarm], [], [AC_MSG_ERROR([I need alarm])]) +AC_CHECK_FUNCS([strerror], [], [AC_MSG_ERROR([I need strerror])]) +AC_CHECK_FUNCS([signal], [], [AC_MSG_ERROR([I need signal])]) +AC_CHECK_FUNCS([popen], [], [AC_MSG_ERROR([I need popen])]) +dnl }}} + +dnl {{{ check for cxxflags +AC_DEFUN([CHECK_CXXFLAG], [ + save_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS $1 -Werror" + AC_MSG_CHECKING([for usable $1 flag]) + AC_COMPILE_IFELSE([ +#include <string> +#include <iostream> +int main(int, char **) +{ + std::string s("test"); + std::cout << s << std::endl; +} + ], + [cxxflag_success=yes], + [cxxflag_success=no]) + AC_MSG_RESULT($cxxflag_success) + CXXFLAGS="$save_CXXFLAGS" + if test "x$cxxflag_success" = "xyes" ; then + CXXFLAGS="$CXXFLAGS $1" + fi + ]) + +AC_MSG_CHECKING([whether our compiler is iccy]) +AC_COMPILE_IFELSE([ +#ifndef __ICC +#error nope +#endif +], + [cxx_compiler_icc=yes], + [cxx_compiler_icc=no]) +AC_MSG_RESULT([${cxx_compiler_icc}]) + +if test "x${cxx_compiler_icc}" = "xyes" ; then + CHECK_CXXFLAG([-Wall]) + CHECK_CXXFLAG([-wd279]) + CHECK_CXXFLAG([-wd304]) + CHECK_CXXFLAG([-wd383]) + CHECK_CXXFLAG([-wd444]) + CHECK_CXXFLAG([-wd488]) + CHECK_CXXFLAG([-wd981]) + CHECK_CXXFLAG([-wd1125]) + CHECK_CXXFLAG([-wd1418]) +elif test "x${ac_cv_cxx_compiler_gnu}" = "xyes" ; then + CHECK_CXXFLAG([-W]) + CHECK_CXXFLAG([-Wall]) + CHECK_CXXFLAG([-Wextra]) + CHECK_CXXFLAG([-Wold-style-cast]) + CHECK_CXXFLAG([-Wno-overloaded-virtual]) + CHECK_CXXFLAG([-Wredundant-decls]) + CHECK_CXXFLAG([-pedantic]) +else + CHECK_CXXFLAG([-Wall]) +fi +dnl }}} + +dnl {{{ doxygen, dot +AC_MSG_CHECKING([whether to enable doxygen]) +AC_ARG_ENABLE([doxygen], + [ --enable-doxygen Enable 'make doxygen' (developer docs)], + [HAVE_DOXYGEN=$enableval + AC_MSG_RESULT([$enableval])], + [AC_MSG_RESULT([autodetect]) + AC_CHECK_PROG(HAVE_DOXYGEN, [doxygen], [yes], [no])]) +AC_SUBST([HAVE_DOXYGEN]) +AM_CONDITIONAL([HAVE_DOXYGEN], test "x$HAVE_DOXYGEN" = "xyes") + +AC_MSG_CHECKING([whether to enable dot]) +AC_ARG_ENABLE([dot], + [ --enable-dot Enable 'HAVE_DOT' in doxygen.conf], + [HAVE_DOT=$enableval + AC_MSG_RESULT([$enableval])], + [AC_MSG_RESULT([autodetect]) + AC_CHECK_PROG(HAVE_DOT, [dot], [yes], [no])]) +AC_SUBST([HAVE_DOT]) +AM_CONDITIONAL([HAVE_DOT], test "x$HAVE_DOT" = "xyes") +dnl }}} + +dnl {{{ built sources +GENERATED_FILE=misc/generated-file.txt +AC_SUBST_FILE(GENERATED_FILE) + +BUILDUSER=`whoami` +AC_SUBST([BUILDUSER]) +BUILDHOST=`hostname` +AC_SUBST([BUILDHOST]) +BUILDDATE=`date` +AC_SUBST([BUILDDATE]) +if test -d "${ac_top_srcdir:-./}/.svn" ; then + SVNVERSION=`svnversion "${ac_top_srcdir:-./}"` +else + SVNVERSION= +fi +AC_SUBST([SVNVERSION]) +dnl }}} + +dnl {{{ output +AM_CONFIG_HEADER(config.h) +AC_OUTPUT( + Makefile + doc/Makefile + doc/doxygen.conf + misc/Makefile + misc/svn-version-filter-data.bash + paludis/Makefile + paludis/about.hh + paludis/args/Makefile + src/Makefile + test/Makefile + ) +dnl }}} + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 000000000..c601740fa --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,23 @@ +CLEANFILES = *~ html/* html +MAINTAINERCLEANFILES = Makefile.in + +docfiles = \ + doc_main.doxygen \ + doc_mainpage.doxygen + +EXTRA_DIST = doxygen.conf.in $(docfiles) + +if HAVE_DOXYGEN + +doxygen : doxygen.conf $(top_srcdir)/paludis/*.cc $(top_srcdir)/paludis/*.hh \ + $(docfiles) + nice doxygen doxygen.conf + +else + +doxygen : + @echo "You don't have doxygen installed!" + exit 1 + +endif + diff --git a/doc/doc_main.doxygen b/doc/doc_main.doxygen new file mode 100644 index 000000000..3afc5b740 --- /dev/null +++ b/doc/doc_main.doxygen @@ -0,0 +1,182 @@ +/* vim: set ft=cpp tw=80 sw=4 et : */ + +/** \namespace test_cases + * Test cases. + * + * \ingroup Test + */ + +/** \namespace test + * Test framework. + * + * \ingroup Test + */ + +/** \namespace paludis::args + * Commandline argument handling. + * + * \ingroup Args + */ + +/** \namespace paludis + * Paludis library code. + */ + +/** \dir paludis + * Paludis library code. + */ + +/** \defgroup DepResolver Dependency parsing and resolution + * Dependency parsing and resolution. + * + * Dependency resolution is handled in stages. We convert a dependency string + * into a tree structure, and then define a visitor over this structure. + * + * \section DepResolverImportant Important Classes + * + * - paludis::DepList creates and holds dependency lists + * - paludis::DepParser turns a dependency string into a paludis::DepAtom + * heirarchy. + */ + +/** \defgroup Environment Environment + * Environment. + * + * These classes represent the environment in which paludis is running. + * + * \section EnvironmentImportant Important Classes + * + * - paludis::Environment represents an environment. + * - paludis::DefaultEnvironment represents the usual environment that should + * be used when writing normal programs (other paludis::Environment + * descendents exist, e.g. for testing). + */ + +/** \defgroup Database Package database functionality + * Package database functionality. + * + * These classes provide checked representations for common data types, as + * well as the core queryable package database functionality. + * + * \section DatabaseImportant Important Classes + * + * - paludis::PackageDatabase represents a package database, which + * is queryable and holds zero or more paludis::Repository instances. + * + * \ingroup Environment + */ + + +/** \defgroup Utility Utilities + * Utilities. + * + * Various miscellaneous utilities. + */ + +/** \defgroup Exception Exception handling + * Exception handling. + * + * All exceptions thrown from paludis should be a subclass of + * paludis::Exception, which provides a message and (via libebt) a backtrace + * giving details of the error. It is probably wise to also check for + * std::exception when writing error handling code. + * + * \section ExceptionImportant Important classes + * + * - paludis::Exception is the base exception class. All exceptions thrown + * by paludis should be descended from this class (although it's best to + * check for std::exception too just in case). + * + * \ingroup Utility + */ + +/** \defgroup Args Command line argument handling + * Command line handling for a program. + * + * Command line handling for a program is done via a subclass of ArgsHandler. + * The class will have member variables of type ArgsGroup to handle groups of + * related arguments, and member variables of subtypes of ArgsOption to handle + * individual switches. + * + * \ingroup Utility + */ + +/** \defgroup Pointer Pointers + * Pointers. + * + * We use shared pointers in various places. Different policies are available + * for different reference count models. + * + * \section PointerImportant Important Classes + * + * - paludis::CountedPtr is used for reference counted pointers. + * + * \ingroup Utility + */ + +/** \defgroup Tokeniser Tokeniser + * Tokeniser. + * + * The paludis::Tokeniser class provides a way of splitting strings into + * smaller strings. + * + * \section TokeniserImportant Important Classes + * + * - paludis::Tokeniser is the main class. + * + * \ingroup Utility + */ + +/** \defgroup Filesystem Filesystem wrapper utilities + * Filesystem wrapper utilities. + * + * The C++ standard library doesn't provide anything for working with + * filesystem entries or directories. Rather than repeatedly making calls + * to stat(2) and opendir(3) all over the place (or using the bloatware + * utilities from Boost), we provide a few lightweight wrapper classes. + * + * \section FilesystemImportant Important Classes + * + * - paludis::FSEntry represents a filesystem entry. + * - paludis::DirIterator is an iterator for directories. + * + * \ingroup Utility + */ + +/** \defgroup PStream Process handling + * Process handling. + * + * The paludis::PStream class can be used to execute a process and get its + * standard output. + * + * \section PStreamImportant Important Classes + * + * - paludis::PStream is a front-end std::istream descendent for process + * invokation. + * + * \ingroup Utility + */ + +/** \defgroup ConfigFile Configuration handling + * Configuration handling. + * + * The paludis::ConfigFile class is a handler for generic configuration files + * using a general line-oriented, comments start with a # format. Various + * subclasses provide interfaces for different file formats. + * + * \section ConfigFileImportant Important Classes + * + * - paludis::KeyValueFile represents a configuration file containing + * KEY="value" type statements. + * - paludis::LineConfigFile represents a configuration file containing + * lines of text. + */ + +/** \defgroup Test Test cases and framework + * Test cases and framework. + * + * Test cases are classes that are descended from TestCase. Declaring an + * instance of a TestCase subclass will register it with the test case + * list. + */ + diff --git a/doc/doc_mainpage.doxygen b/doc/doc_mainpage.doxygen new file mode 100644 index 000000000..e5f43e7f2 --- /dev/null +++ b/doc/doc_mainpage.doxygen @@ -0,0 +1,28 @@ +/* vim: set ft=cpp tw=80 sw=4 et : */ + +/** \mainpage + * + * \section developerdocs For Developers + * + * It's best to start by skimming over the main program to get a feel for how + * everything fits together. Useful files: + * + * - src/paludis.cc The main program. + * - src/query.cc The --query action handler. + * - src/install.cc The --install action handler. + * + * After that, the following classes are good places to begin: + * + * - paludis::DefaultEnvironment provides a representation of the default + * operating environment. + * - paludis::PackageDatabase provides routines for querying packages. An + * instance can be obtained via paludis::DefaultEnvironment. + * + * The <a href="modules.html">Modules</a> link in the header bar will probably + * be of more use than any of the full class lists. + * + * \section userdocs For End Users + * + * You shouldn't be touching paludis at the moment. Go away. + * + */ diff --git a/doc/doxygen.conf.in b/doc/doxygen.conf.in new file mode 100644 index 000000000..c7159cfb8 --- /dev/null +++ b/doc/doxygen.conf.in @@ -0,0 +1,1223 @@ +# Doxyfile 1.4.2 + +@GENERATED_FILE@ + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = @PACKAGE@ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = "Version @VERSION@" + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = "../misc/svn-version-filter.bash" + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../paludis ../paludis/args ../test ../doc + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.hh *.cc *.doxygen + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = ../ + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = "grep -v '^#define .*_GUARD_'" + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +### HTML_HEADER = header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +### HTML_FOOTER = footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +### DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = @HAVE_DOT@ + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + + + diff --git a/misc/Makefile.am b/misc/Makefile.am new file mode 100644 index 000000000..91a5cf3e9 --- /dev/null +++ b/misc/Makefile.am @@ -0,0 +1,4 @@ +CLEANFILES = *~ +MAINTAINERCLEANFILES = Makefile.in svn-version-filter-data.bash +EXTRA_DIST = generated-file.txt svn-version-filter-data.bash.in + diff --git a/misc/generated-file.txt b/misc/generated-file.txt new file mode 100644 index 000000000..25c83f24c --- /dev/null +++ b/misc/generated-file.txt @@ -0,0 +1,9 @@ +#if 0 +# vim: set ro : + +# ********************************************************* +# THIS IS A GENERATED FILE! DO NOT EDIT THIS FILE DIRECTLY! +# ********************************************************* +# +#endif + diff --git a/misc/svn-version-filter-data.bash.in b/misc/svn-version-filter-data.bash.in new file mode 100644 index 000000000..6b4b2492d --- /dev/null +++ b/misc/svn-version-filter-data.bash.in @@ -0,0 +1 @@ +export VERSION=@VERSION@ diff --git a/misc/svn-version-filter.bash b/misc/svn-version-filter.bash new file mode 100755 index 000000000..38a36b74d --- /dev/null +++ b/misc/svn-version-filter.bash @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# For Doxygen. See: +# http://www.stack.nl/~dimitri/doxygen/config.html#cfg_file_version_filter + +source ${0/.bash/-data.bash} + +case $1 in + *.svn*) + echo $VERSION + ;; + + *) + case "$(basename $1 )" in + *.cc|*.hh|*.hh.in) + if type svn &>/dev/null ; then + echo -n "svn " + svn stat -v $1 | sed -n 's/^[ A-Z?\*|!]\{1,15\}/r/;s/ \{1,15\}/\/r/;s/ .*//p' + else + echo $VERSION + fi + ;; + + *) + echo $VERSION + ;; + esac + ;; +esac + diff --git a/paludis/Makefile.am.m4 b/paludis/Makefile.am.m4 new file mode 100644 index 000000000..df69f7407 --- /dev/null +++ b/paludis/Makefile.am.m4 @@ -0,0 +1,39 @@ +ifdef(`__gnu__',`',`errprint(`This is not GNU m4... +')m4exit(1)') include(`misc/generated-file.txt') + +dnl vim: set ft=m4 et : + +define(`filelist', `')dnl +define(`testlist', `')dnl +define(`addtest', `define(`testlist', testlist `$1_TEST') +$1_TEST_SOURCES = $1_TEST.cc +$1_TEST_LDADD = $(top_builddir)/test/libtest.a libpaludis.a +')dnl +define(`addhh', `define(`filelist', filelist `$1.hh')')dnl +define(`addcc', `define(`filelist', filelist `$1.cc')')dnl +define(`addimpl', `define(`filelist', filelist `$1-impl.hh')')dnl +define(`addthis', `dnl +ifelse(`$2', `hh', `addhh(`$1')', `')dnl +ifelse(`$2', `cc', `addcc(`$1')', `')dnl +ifelse(`$2', `impl', `addimpl(`$1')', `')dnl +ifelse(`$2', `test', `addtest(`$1')', `')')dnl +define(`add', `addthis(`$1',`$2')addthis(`$1',`$3')addthis(`$1',`$4')dnl +addthis(`$1',`$5')addthis(`$1',`$6')')dnl + +include(`paludis/files.m4') + +CLEANFILES = *~ +MAINTAINERCLEANFILES = Makefile.in Makefile.am about.hh paludis.hh smart_record.hh comparison_policy.hh +AM_CXXFLAGS = -I$(top_srcdir) +DEFS=-DSYSCONFDIR=\"$(sysconfdir)\" +EXTRA_DIST = about.hh.in Makefile.am.m4 paludis.hh.m4 files.m4 smart_record.hh.m4 comparison_policy.hh.m4 +SUBDIRS = . args + +libpaludis_a_SOURCES = filelist + +TESTS = testlist + +TESTS_ENVIRONMENT = $(SHELL) $(top_srcdir)/test/run_test.sh +noinst_PROGRAMS = $(TESTS) +noinst_LIBRARIES = libpaludis.a + diff --git a/paludis/about.hh.in b/paludis/about.hh.in new file mode 100644 index 000000000..e31b11837 --- /dev/null +++ b/paludis/about.hh.in @@ -0,0 +1,67 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 + */ + +@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. + */ + +/// The package name (eg Paludis) +#define PALUDIS_PACKAGE "@PACKAGE@" + +/// The major version (eg 0.4.1 -> 0) +#define PALUDIS_VERSION_MAJOR @VERSION_MAJOR@ + +/// The minor version (eg 0.4.1 -> 4) +#define PALUDIS_VERSION_MINOR @VERSION_MINOR@ + +/// The micro version (eg 0.4.1 -> 1) +#define PALUDIS_VERSION_MICRO @VERSION_MICRO@ + +/// The version, two digits per part (eg 1.3.5 -> 10305) +#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 ""). +#define PALUDIS_SUBVERSION_REVISION "@SVNVERSION@" + +/// The CXXFLAGS used to build Paludis. +#define PALUDIS_BUILD_CXXFLAGS "@CXXFLAGS@" + +/// The LDFLAGS used to build Paludis. +#define PALUDIS_BUILD_LDFLAGS "@LDFLAGS@" + +/// The compiler used to build Paludis. +#define PALUDIS_BUILD_CXX "@CXX@" + +/// The user who built Paludis. +#define PALUDIS_BUILD_USER "@BUILDUSER@" + +/// The host on which Paludis was built. +#define PALUDIS_BUILD_HOST "@BUILDHOST@" + +/// The date when Paludis was built. +#define PALUDIS_BUILD_DATE "@BUILDDATE@" + +#endif diff --git a/paludis/about_TEST.cc b/paludis/about_TEST.cc new file mode 100644 index 000000000..66b7c0b1c --- /dev/null +++ b/paludis/about_TEST.cc @@ -0,0 +1,86 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "about.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace test; +using namespace paludis; + +/** + * \file + * Test cases for about.hh . + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Version tests. + * + * \ingroup Test + */ + 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. + * + * \ingroup Test + */ + 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/paludis/all_dep_atom.cc b/paludis/all_dep_atom.cc new file mode 100644 index 000000000..4db11fe93 --- /dev/null +++ b/paludis/all_dep_atom.cc @@ -0,0 +1,31 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include "visitor_pattern-impl.hh" + +using namespace paludis; + +AllDepAtom::AllDepAtom() +{ +} diff --git a/paludis/all_dep_atom.hh b/paludis/all_dep_atom.hh new file mode 100644 index 000000000..9d499e56c --- /dev/null +++ b/paludis/all_dep_atom.hh @@ -0,0 +1,51 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ALL_DEP_ATOM_HH +#define PALUDIS_GUARD_PALUDIS_ALL_DEP_ATOM_HH 1 + +#include <paludis/composite_dep_atom.hh> +#include <paludis/dep_atom_visitor.hh> + +/** \file + * Declarations for the AllDepAtom class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * Represents a ( first second third ) or top level group of dependency + * atoms. + * + * \ingroup DepResolver + */ + class AllDepAtom : public CompositeDepAtom, + public Visitable<AllDepAtom, DepAtomVisitor> + { + public: + /** + * Constructor. + */ + AllDepAtom(); + }; +} + +#endif diff --git a/paludis/all_masked_error.cc b/paludis/all_masked_error.cc new file mode 100644 index 000000000..5490c0c43 --- /dev/null +++ b/paludis/all_masked_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "all_masked_error.hh" + +using namespace paludis; + +AllMaskedError::AllMaskedError(const std::string & query) throw () : + DepListError("Error searching for '" + query + "': no available versions") +{ +} + diff --git a/paludis/all_masked_error.hh b/paludis/all_masked_error.hh new file mode 100644 index 000000000..0471007f9 --- /dev/null +++ b/paludis/all_masked_error.hh @@ -0,0 +1,40 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ALL_MASKED_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_ALL_MASKED_ERROR_HH 1 + +#include <paludis/dep_list_error.hh> + +namespace paludis +{ + /** + * Thrown if all versions of a particular atom are masked. + */ + class AllMaskedError : public DepListError + { + public: + /** + * Constructor. + */ + AllMaskedError(const std::string & query) throw (); + }; +} + +#endif diff --git a/paludis/ambiguous_package_name_error.cc b/paludis/ambiguous_package_name_error.cc new file mode 100644 index 000000000..8610645e3 --- /dev/null +++ b/paludis/ambiguous_package_name_error.cc @@ -0,0 +1,23 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "ambiguous_package_name_error.hh" + +using namespace paludis; + diff --git a/paludis/ambiguous_package_name_error.hh b/paludis/ambiguous_package_name_error.hh new file mode 100644 index 000000000..4b4c4f45a --- /dev/null +++ b/paludis/ambiguous_package_name_error.hh @@ -0,0 +1,62 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_AMBIGUOUS_PACKAGE_NAME_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_AMBIGUOUS_PACKAGE_NAME_ERROR_HH 1 + +#include <paludis/package_database_lookup_error.hh> +#include <paludis/join.hh> + +/** \file + * Declarations for AmbiguousPackageNameError. + * + * \ingroup Exception + * \ingroup Database + */ + +namespace paludis +{ + /** + * Thrown if a PackageDatabase query results in more than one matching + * Package. + * + * \ingroup Exception + * \ingroup Database + */ + class AmbiguousPackageNameError : public PackageDatabaseLookupError + { + public: + /** + * Constructor. + */ + template <typename I_> + AmbiguousPackageNameError(const std::string & name, + I_ begin, const I_ end) throw (); + }; + + template <typename I_> + AmbiguousPackageNameError::AmbiguousPackageNameError(const std::string & name, + I_ begin, const I_ end) throw () : + PackageDatabaseLookupError("Ambiguous package name '" + name + "' (candidates are " + + join(begin, end, ", ") + ")") + { + } +} + +#endif diff --git a/paludis/any_dep_atom.cc b/paludis/any_dep_atom.cc new file mode 100644 index 000000000..e2432b699 --- /dev/null +++ b/paludis/any_dep_atom.cc @@ -0,0 +1,32 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include "visitor_pattern-impl.hh" + +using namespace paludis; + +AnyDepAtom::AnyDepAtom() +{ +} + diff --git a/paludis/any_dep_atom.hh b/paludis/any_dep_atom.hh new file mode 100644 index 000000000..002471b5d --- /dev/null +++ b/paludis/any_dep_atom.hh @@ -0,0 +1,51 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ANY_DEP_ATOM_HH +#define PALUDIS_GUARD_PALUDIS_ANY_DEP_ATOM_HH 1 + +#include <paludis/composite_dep_atom.hh> + +/** \file + * Declarations for AnyDepAtom. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + class DepAtomVisitor; + + /** + * Represents a "|| ( )" dependency block. + * + * \ingroup DepResolver + */ + class AnyDepAtom : public CompositeDepAtom, + public Visitable<AnyDepAtom, DepAtomVisitor> + { + public: + /** + * Constructor. + */ + AnyDepAtom(); + }; +} + +#endif diff --git a/paludis/args/Makefile.am b/paludis/args/Makefile.am new file mode 100644 index 000000000..e114af515 --- /dev/null +++ b/paludis/args/Makefile.am @@ -0,0 +1,30 @@ +CLEANFILES = *~ +MAINTAINERCLEANFILES = Makefile.in +AM_CXXFLAGS = -I$(top_srcdir) + +TESTS = \ + args_TEST + +libpaludisargs_a_SOURCES = \ + alias_arg.hh alias_arg.cc \ + args.hh args.cc \ + args_error.hh args_error.cc \ + args_group.hh args_group.cc \ + args_handler.hh args_handler.cc \ + args_option.hh args_option.cc \ + bad_argument.hh bad_argument.cc \ + switch_arg.hh switch_arg.cc \ + args_visitor.hh args_visitor.cc \ + bad_value.hh bad_value.cc + +noinst_LIBRARIES = libpaludisargs.a +noinst_PROGRAMS = $(TESTS) + +test_ldadd = \ + libpaludisargs.a \ + $(top_builddir)/test/libtest.a \ + $(top_builddir)/paludis/libpaludis.a + +args_TEST_SOURCES = args_TEST.cc +args_TEST_LDADD = $(test_ldadd) + diff --git a/paludis/args/alias_arg.cc b/paludis/args/alias_arg.cc new file mode 100644 index 000000000..8c930c55a --- /dev/null +++ b/paludis/args/alias_arg.cc @@ -0,0 +1,38 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "alias_arg.hh" +#include "args_group.hh" +#include "args_handler.hh" + +/** \file + * Implementation for AliasArg. + * + * \ingroup Args + */ + +using namespace paludis::args; + +AliasArg::AliasArg(ArgsOption * const other, const std::string & long_name) : + ArgsOption(other->group(), long_name, '\0', "Alias for --" + other->long_name()), + _other(other) +{ + other->group()->handler()->add_option(other, long_name); +} + diff --git a/paludis/args/alias_arg.hh b/paludis/args/alias_arg.hh new file mode 100644 index 000000000..e1546676b --- /dev/null +++ b/paludis/args/alias_arg.hh @@ -0,0 +1,70 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ALIAS_ARG_HH +#define PALUDIS_GUARD_PALUDIS_ARGS_ALIAS_ARG_HH 1 + +#include <paludis/args/args_option.hh> +#include <string> + +/** \file + * Declaration for AliasArg. + * + * \ingroup Args + */ + +namespace paludis +{ + namespace args + { + /** + * An AliasArg is an alias for another argument. + * + * \ingroup Args + */ + class AliasArg : public ArgsOption + { + 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); + } + + void accept(ArgsVisitor * const v) + { + v->visit(this); + } + }; + } +} + +#endif diff --git a/paludis/args/args.cc b/paludis/args/args.cc new file mode 100644 index 000000000..2433110f7 --- /dev/null +++ b/paludis/args/args.cc @@ -0,0 +1,27 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "args.hh" + +/** \file + * Implementation for args.hh . + * + * \ingroup Args + */ + diff --git a/paludis/args/args.hh b/paludis/args/args.hh new file mode 100644 index 000000000..f9c8b2f3f --- /dev/null +++ b/paludis/args/args.hh @@ -0,0 +1,37 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_HH +#define PALUDIS_GUARD_ARGS_ARGS_HH 1 + +/** \file + * Master include file for command line argument handling. + * + * \ingroup Args + */ + +#include <paludis/args/alias_arg.hh> +#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> +#include <paludis/args/switch_arg.hh> + +#endif diff --git a/paludis/args/args_TEST.cc b/paludis/args/args_TEST.cc new file mode 100644 index 000000000..4b0207e72 --- /dev/null +++ b/paludis/args/args_TEST.cc @@ -0,0 +1,102 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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.hh> +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace paludis; +using namespace paludis::args; +using namespace test; + +/** \file + * Test cases for paludis::args things. + */ + +#ifndef DOXYGEN + +static const char * const arg_enum_args[3] = { "one", "two", "three" }; + +struct CommandLine : public ArgsHandler +{ + ArgsGroup group_one; + SwitchArg arg_foo; + SwitchArg arg_bar; + SwitchArg arg_dummy; + + ArgsGroup group_two; + SwitchArg arg_baz; + AliasArg arg_other_baz; + StringArg arg_something; + IntegerArg arg_somenum; + EnumArg arg_enum; + + CommandLine() : + group_one(this, "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"), + + group_two(this, "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_somenum(&group_two, "num", 'n', "Some number"), + arg_enum(&group_two, "enum", 'e', "One of three", arg_enum_args) + { + } +}; + +#endif + +namespace test_cases +{ + /** + * \test Simple args tests. + */ + struct ArgsTestSimple : TestCase + { + ArgsTestSimple() : TestCase("simple") { } + + void run() + { + char * args[] = { "program-name", "--other-baz", "-fsne", "blah", "7", "three", "--", "--dummy", + "one", "two" }; + CommandLine c1; + c1.run(10, 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_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; +} + diff --git a/paludis/args/args_error.cc b/paludis/args/args_error.cc new file mode 100644 index 000000000..6e9bd2be3 --- /dev/null +++ b/paludis/args/args_error.cc @@ -0,0 +1,35 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "args_error.hh" + +/** \file + * Implementation for ArgsError. + * + * \ingroup Args + * \ingroup Exception + */ + +using namespace paludis::args; + +ArgsError::ArgsError(const std::string & message) throw () : + paludis::Exception("Error handling command line: " + message) +{ +} + diff --git a/paludis/args/args_error.hh b/paludis/args/args_error.hh new file mode 100644 index 000000000..ee0685132 --- /dev/null +++ b/paludis/args/args_error.hh @@ -0,0 +1,54 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ERROR_HH +#define PALUDIS_GUARD_ARGS_ARGS_ERROR_HH 1 + +#include <paludis/exception.hh> +#include <string> + +/** \file + * Declaration for ArgsError. + * + * \ingroup Args + * \ingroup Exception + */ + +namespace paludis +{ + namespace args + { + /** + * Thrown if an invalid command line argument is provided. + * + * \ingroup Args + * \ingroup Exception + */ + class ArgsError : public paludis::Exception + { + protected: + /** + * Constructor. + */ + ArgsError(const std::string & message) throw (); + }; + } +} + +#endif diff --git a/paludis/args/args_group.cc b/paludis/args/args_group.cc new file mode 100644 index 000000000..25c1fadf7 --- /dev/null +++ b/paludis/args/args_group.cc @@ -0,0 +1,43 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "args.hh" + +/** \file + * Implementation for ArgsGroup. + * + * \ingroup Args + */ + +using namespace paludis::args; + +ArgsGroup::ArgsGroup(ArgsHandler * h, const std::string & name) : + _name(name), + _handler(h) +{ + h->add(this); +} + +void +ArgsGroup::add(ArgsOption * const value) +{ + /// \bug Should check for uniqueness of short and long names. + _args_options.push_back(value); +} + diff --git a/paludis/args/args_group.hh b/paludis/args/args_group.hh new file mode 100644 index 000000000..643eb3159 --- /dev/null +++ b/paludis/args/args_group.hh @@ -0,0 +1,93 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_GROUP_HH +#define PALUDIS_GUARD_ARGS_ARGS_GROUP_HH 1 + +#include <paludis/args/args_option.hh> +#include <list> +#include <string> + +/** \file + * Declaration for ArgsGroup. + * + * \ingroup Args + */ + +namespace paludis +{ + + namespace args + { + class ArgsHandler; + + /** + * Contains a related group of command line arguments. + * + * \ingroup Args + */ + class ArgsGroup + { + friend class ArgsHandler; + friend class ArgsOption; + + private: + ArgsGroup(const ArgsGroup &); + + void operator= (const ArgsGroup &); + + const std::string _name; + + std::list<ArgsOption *> _args_options; + + ArgsHandler * _handler; + + protected: + /** + * Add an ArgsOption instance (called by the ArgsOption + * constructor). + */ + void add(ArgsOption * const value); + + public: + /** + * Constructor. + */ + ArgsGroup(ArgsHandler * h, const std::string & name); + + /** + * Fetch our name. + */ + const std::string & name() const + { + return _name; + } + + /** + * Fetch our handler. + */ + ArgsHandler * handler() const + { + return _handler; + } + }; + } +} + +#endif diff --git a/paludis/args/args_handler.cc b/paludis/args/args_handler.cc new file mode 100644 index 000000000..0cbfd6ace --- /dev/null +++ b/paludis/args/args_handler.cc @@ -0,0 +1,130 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "args.hh" + +/** \file + * Implementation for ArgsHandler. + * + * \ingroup Args + */ + +using namespace paludis::args; + +ArgsHandler::ArgsHandler() +{ +} + +void +ArgsHandler::add(ArgsGroup * const g) +{ + /// \bug Should check for name uniqueness. + _groups.push_back(g); +} + +#ifndef DOXYGEN +struct Found +{ +}; +#endif + +void +ArgsHandler::run(const int argc, const char * const * const argv) +{ + std::list<std::string> args(argv + 1, &argv[argc]); + std::list<std::string>::iterator argit = args.begin(), arge = args.end(); + + ArgsVisitor visitor(&argit); + + 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 = _longopts.find(arg); + if(it == _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 = _shortopts.find(*c); + if(it == _shortopts.end()) + { + throw BadArgument(std::string("-") + *c); + } + (*it).second->accept(&visitor); + } + } + else + { + _parameters.push_back(arg); + } + } + + _parameters.insert(_parameters.end(), argit, args.end()); +} + +void +ArgsHandler::dump_to_stream(std::ostream & s) const +{ + std::list<ArgsGroup *>::const_iterator g(_groups.begin()), g_end(_groups.end()); + for ( ; g != g_end ; ++g) + { + s << (*g)->name() << ":" << std::endl; + + std::list<ArgsOption *>::const_iterator a((*g)->_args_options.begin()), + a_end((*g)->_args_options.end()); + for ( ; a != a_end ; ++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(), ' '); + s << p.str(); + s << " " << (*a)->description() << std::endl; + } + + s << std::endl; + } +} + +#ifndef DOXYGEN +std::ostream & +paludis::args::operator<< (std::ostream & s, const ArgsHandler & h) +{ + h.dump_to_stream(s); + return s; +} +#endif + diff --git a/paludis/args/args_handler.hh b/paludis/args/args_handler.hh new file mode 100644 index 000000000..9203d0e88 --- /dev/null +++ b/paludis/args/args_handler.hh @@ -0,0 +1,129 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_HANDLER_HH +#define PALUDIS_GUARD_ARGS_ARGS_HANDLER_HH 1 + +#include <paludis/args/args_group.hh> +#include <paludis/instantiation_policy.hh> +#include <string> +#include <ostream> +#include <map> + +/** \file + * Declaration for ArgsHandler. + * + * \ingroup Args + */ + +namespace paludis +{ + namespace args + { + /** + * Handles command line arguments. + * + * \ingroup Args + */ + class ArgsHandler : private InstantiationPolicy<ArgsHandler, instantiation_method::NonCopyableTag> + { + friend class ArgsGroup; + friend std::ostream & operator<< (std::ostream &, const ArgsHandler &); + + private: + std::list<ArgsGroup *> _groups; + std::list<std::string> _parameters; + + std::map<std::string, ArgsOption *> _longopts; + std::map<char, ArgsOption *> _shortopts; + + protected: + /** + * 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: + /** + * Constructor. + */ + ArgsHandler(); + + /** + * Parse command line arguments. + */ + void run(const int, const char * const * const); + + /** + * Iterate over our parameters (non - and -- switches and their + * values). + */ + typedef std::list<std::string>::const_iterator ParametersIterator; + + /** + * Pointer to the start of our parameters. + */ + ParametersIterator begin_parameters() const + { + return _parameters.begin(); + } + + /** + * Pointer to past the end of our parameters. + */ + ParametersIterator end_parameters() const + { + return _parameters.end(); + } + + /** + * Do we have no parameters? + */ + bool empty() const + { + return _parameters.empty(); + } + + /** + * Add an ArgsOption instance. + */ + void add_option(ArgsOption *opt, const std::string long_name, const char short_name = '\0') + { + _longopts[long_name] = opt; + if (short_name != '\0') + _shortopts[short_name] = opt; + } + + }; + + /** + * Output an ArgsHandler to an ostream, for --help output. + * + * \ingroup Args + */ + std::ostream & operator<< (std::ostream &, const ArgsHandler &); + } +} + +#endif diff --git a/paludis/args/args_option.cc b/paludis/args/args_option.cc new file mode 100644 index 000000000..7ec879d01 --- /dev/null +++ b/paludis/args/args_option.cc @@ -0,0 +1,68 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "args.hh" +#include "bad_value.hh" + +/** \file + * Implementation for ArgsOption. + * + * \ingroup Args + */ + +using namespace paludis::args; + +ArgsOption::ArgsOption(ArgsGroup * const g, const std::string & long_name, + const char short_name, const std::string & description) : + _group(g), + _long_name(long_name), + _short_name(short_name), + _description(description), + _specified(false) +{ + g->add(this); + g->_handler->add_option(this, long_name, short_name); +} + +StringArg::StringArg(ArgsGroup * const g, const std::string & long_name, + const char short_name, const std::string & description) : + ArgsOption(g, long_name, short_name, description) +{ +} + +SwitchArg::SwitchArg(ArgsGroup * const group, std::string long_name, char short_name, + std::string description) : + ArgsOption(group, long_name, short_name, description) +{ +} + +IntegerArg::IntegerArg(ArgsGroup * const group, const std::string& long_name, + char short_name, const std::string& description) : + ArgsOption(group, long_name, short_name, description) +{ +} + +void EnumArg::set_argument(const std::string & arg) +{ + if(_allowed_args.find(arg) == _allowed_args.end()) + { + throw(BadValue("--" + long_name(), arg)); + } + _argument = arg; +} diff --git a/paludis/args/args_option.hh b/paludis/args/args_option.hh new file mode 100644 index 000000000..47d9d478c --- /dev/null +++ b/paludis/args/args_option.hh @@ -0,0 +1,240 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 <string> +#include <set> +#include "args_visitor.hh" + +/** \file + * Declaration for ArgsOption. + * + * \ingroup Args + */ + +namespace paludis +{ + namespace args + { + class ArgsGroup; + + /** + * Base class for a command line option. + * + * \ingroup Args + */ + class ArgsOption + { + 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); + + public: + /** + * 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; + } + + /** + * Destructor. + */ + virtual ~ArgsOption() + { + } + + /** + * Accept a visitor. + */ + virtual void accept(ArgsVisitor * const) = 0; + }; + + /** + * An option that takes a string argument. + * + * \ingroup Args + */ + class StringArg : public ArgsOption + { + private: + std::string _argument; + + public: + + /** + * Constructor + */ + StringArg(ArgsGroup * const, const std::string & long_name, + const char short_name, const std::string & description); + + /** + * 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) { _argument = arg; } + + void accept(ArgsVisitor * const v) + { + v->visit(this); + } + }; + + /** + * An option that takes an integer argument. + * + * \ingroup Args + */ + class IntegerArg : public ArgsOption + { + 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; } + + void accept(ArgsVisitor * const v) + { + v->visit(this); + } + }; + + /** + * An option that takes one of a predefined set of string arguments. + * + * \ingroup Args + */ + class EnumArg : public ArgsOption + { + private: + const std::set<std::string> _allowed_args; + std::string _argument; + + public: + /** + * Constructor. + */ + template <typename T_> + EnumArg(ArgsGroup * const group, const std::string & long_name, + const char short_name, const std::string & description, + const T_ * allowed_args) : + ArgsOption(group, long_name, short_name, description), + _allowed_args(&allowed_args[0], &allowed_args[sizeof(allowed_args)-1]) + { + } + + /** + * 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); + + void accept(ArgsVisitor * const v) + { + v->visit(this); + } + }; + } +} + +#endif diff --git a/paludis/args/args_visitor.cc b/paludis/args/args_visitor.cc new file mode 100644 index 000000000..d3648d185 --- /dev/null +++ b/paludis/args/args_visitor.cc @@ -0,0 +1,74 @@ +#include "args_visitor.hh" +#include "args_option.hh" +#include "alias_arg.hh" +#include "switch_arg.hh" + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "bad_value.hh" + +#include <sstream> + +using namespace paludis; +using namespace args; + +ArgsVisitor::ArgsVisitor(std::list<std::string>::iterator *ai) : _args_index(ai) +{ +} + +void ArgsVisitor::visit(ArgsOption * const arg) +{ + arg->set_specified(true); +} + +void ArgsVisitor::visit(StringArg * const arg) +{ + visit(static_cast<ArgsOption *>(arg)); + arg->set_argument(*++(*_args_index)); +} + +void ArgsVisitor::visit(AliasArg * const arg) +{ + visit(static_cast<ArgsOption *>(arg)); +} + +void ArgsVisitor::visit(SwitchArg * const arg) +{ + visit(static_cast<ArgsOption *>(arg)); +} + +void ArgsVisitor::visit(IntegerArg * const arg) +{ + visit(static_cast<ArgsOption*>(arg)); + std::stringstream ss; + std::string param = *++(*_args_index); + ss << param; + int i; + ss >> i; + if(!ss.eof() || ss.bad()) + { + throw BadValue("--" + arg->long_name(), param); + } + arg->set_argument(i); +} + +void ArgsVisitor::visit(EnumArg * const arg) +{ + visit(static_cast<ArgsOption*>(arg)); + arg->set_argument(*++(*_args_index)); +} diff --git a/paludis/args/args_visitor.hh b/paludis/args/args_visitor.hh new file mode 100644 index 000000000..8fd8e71ed --- /dev/null +++ b/paludis/args/args_visitor.hh @@ -0,0 +1,77 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 <list> + +/** \file + * Declaration for ArgsVisitor + * + * \ingroup Args + */ + +namespace paludis +{ + namespace args + { + class ArgsOption; + class StringArg; + class AliasArg; + class SwitchArg; + class IntegerArg; + class EnumArg; + + /** + * Visitor class. Processes command-line options as they are found. + */ + class ArgsVisitor + { + private: + std::list<std::string>::iterator *_args_index; + + public: + /** + * Constructor + */ + ArgsVisitor(std::list<std::string>::iterator *); + + /// Visit an ArgsOption. + void visit(ArgsOption * const); + + /// Visit a StringArg. + void visit(StringArg * const); + + /// Visit an AliasArg. + void visit(AliasArg * const); + + /// Visit a SwitchArg. + void visit(SwitchArg * const); + + /// Visit an IntegerArg. + void visit(IntegerArg * const); + + /// Visit an EnumArg. + void visit(EnumArg * const); + }; + } +} + +#endif diff --git a/paludis/args/bad_argument.cc b/paludis/args/bad_argument.cc new file mode 100644 index 000000000..4108c3e33 --- /dev/null +++ b/paludis/args/bad_argument.cc @@ -0,0 +1,35 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "bad_argument.hh" + +/** \file + * Implementation for BadArgument. + * + * \ingroup Args + * \ingroup Exception + */ + +using namespace paludis::args; + +BadArgument::BadArgument(const std::string & option) throw () : + ArgsError("Bad argument '" + option + "'") +{ +} + diff --git a/paludis/args/bad_argument.hh b/paludis/args/bad_argument.hh new file mode 100644 index 000000000..c5481528d --- /dev/null +++ b/paludis/args/bad_argument.hh @@ -0,0 +1,53 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_BAD_ARGUMENT_HH +#define PALUDIS_GUARD_ARGS_BAD_ARGUMENT_HH 1 + +#include <paludis/args/args_error.hh> + +/** \file + * Declaration for BadArgument. + * + * \ingroup Args + * \ingroup Exception + */ + +namespace paludis +{ + namespace args + { + /** + * Thrown if an unrecognised command line argument is specified. + * + * \ingroup Args + * \ingroup Exception + */ + class BadArgument : public ArgsError + { + public: + /** + * Constructor. + */ + BadArgument(const std::string & option) throw (); + }; + } +} + +#endif diff --git a/paludis/args/bad_value.cc b/paludis/args/bad_value.cc new file mode 100644 index 000000000..b6a6271d9 --- /dev/null +++ b/paludis/args/bad_value.cc @@ -0,0 +1,32 @@ +#include "bad_value.hh" + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 + */ + +/** \file + * Implementation for BadValue + * + * \ingroup Args + * \ingroup Exception + */ + +using namespace paludis::args; + +BadValue::BadValue(const std::string& option, const std::string& value) throw () : + ArgsError("Invalid parameter '" + value + "' for argument '" + option + "'") +{ +} diff --git a/paludis/args/bad_value.hh b/paludis/args/bad_value.hh new file mode 100644 index 000000000..427f1bd48 --- /dev/null +++ b/paludis/args/bad_value.hh @@ -0,0 +1,51 @@ +#ifndef PALUDIS_GUARD_ARGS_BAD_VALUE_HH +#define PALUDIS_GUARD_ARGS_BAD_VALUE_HH 1 + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_error.hh> + +/** \file + * Declaration for BadValue. + * + * \ingroup Args + * \ingroup Exception + */ + +namespace paludis +{ + namespace args + { + /** + * Thrown if an invalid parameter is passed to a valid command line argument. + * + * \ingroup Args + * \ingroup Exception + */ + class BadValue : public ArgsError + { + public: + /** + * Constructor + */ + BadValue(const std::string& option, const std::string& value) throw(); + }; + } +} + +#endif diff --git a/paludis/args/switch_arg.cc b/paludis/args/switch_arg.cc new file mode 100644 index 000000000..72976a0b2 --- /dev/null +++ b/paludis/args/switch_arg.cc @@ -0,0 +1,35 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "switch_arg.hh" + +/** \file + * Implementation for SwitchArg. + * + * \ingroup Args + */ + +using namespace paludis::args; + +SwitchArg::SwitchArg(ArgsGroup * const group, std::string long_name, char short_name, + std::string description) : + ArgsOption(group, long_name, short_name, description) +{ +} + diff --git a/paludis/args/switch_arg.hh b/paludis/args/switch_arg.hh new file mode 100644 index 000000000..fd85e0699 --- /dev/null +++ b/paludis/args/switch_arg.hh @@ -0,0 +1,59 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_SWITCH_ARG_HH +#define PALUDIS_GUARD_ARGS_SWITCH_ARG_HH 1 + +#include <paludis/args/args_option.hh> +#include <string> + +/** \file + * Declaration for SwitchArg. + * + * \ingroup Args + */ + +namespace paludis +{ + namespace args + { + /** + * A SwitchArg is an option that can either be specified or not + * specified, and that takes no value (for example, --help). + * + * \ingroup Args + */ + class SwitchArg : public ArgsOption + { + public: + /** + * Constructor. + */ + SwitchArg(ArgsGroup * const group, std::string long_name, char short_name, + std::string description); + + void accept(ArgsVisitor * const v) + { + v->visit(this); + } + }; + } +} + +#endif diff --git a/paludis/attributes.cc b/paludis/attributes.cc new file mode 100644 index 000000000..c6b5791b3 --- /dev/null +++ b/paludis/attributes.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "attributes.hh" + diff --git a/paludis/attributes.hh b/paludis/attributes.hh new file mode 100644 index 000000000..b462767cf --- /dev/null +++ b/paludis/attributes.hh @@ -0,0 +1,42 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ATTRIBUTES_HH +#define PALUDIS_GUARD_PALUDIS_ATTRIBUTES_HH 1 + +/** \file + * Declare the PALUDIS_ATTRIBUTE macro. + */ + +/** \def PALUDIS_ATTRIBUTE + * If we're using GCC, expands to __attribute__, otherwise discards its + * arguments. + */ + +#ifdef __GNUC__ +# if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define PALUDIS_ATTRIBUTE(x) __attribute__(x) +# else +# define PALUDIS_ATTRIBUTE(x) +# endif +#else +# define PALUDIS_ATTRIBUTE(x) +#endif + +#endif diff --git a/paludis/bad_version_spec_error.cc b/paludis/bad_version_spec_error.cc new file mode 100644 index 000000000..e283554dc --- /dev/null +++ b/paludis/bad_version_spec_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "bad_version_spec_error.hh" + +using namespace paludis; + +BadVersionSpecError::BadVersionSpecError(const std::string & name) throw () : + NameError(name, "version spec") +{ +} + diff --git a/paludis/bad_version_spec_error.hh b/paludis/bad_version_spec_error.hh new file mode 100644 index 000000000..b9b1059f9 --- /dev/null +++ b/paludis/bad_version_spec_error.hh @@ -0,0 +1,50 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_BAD_VERSION_SPEC_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_BAD_VERSION_SPEC_ERROR_HH 1 + +#include <paludis/name_error.hh> + +/** \file + * Declarations for the VersionSpec class. + * + * \ingroup Exception + * \ingroup Database + */ + +namespace paludis +{ + /** + * Thrown if a VersionSpec is created from an invalid version string. + * + * \ingroup Exception + * \ingroup Database + */ + class BadVersionSpecError : public NameError + { + public: + /** + * Constructor. + */ + BadVersionSpecError(const std::string & name) throw (); + }; +} + +#endif diff --git a/paludis/block_dep_atom.cc b/paludis/block_dep_atom.cc new file mode 100644 index 000000000..e0e94b4d8 --- /dev/null +++ b/paludis/block_dep_atom.cc @@ -0,0 +1,34 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "block_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include "visitor_pattern-impl.hh" + +using namespace paludis; + +BlockDepAtom::BlockDepAtom(PackageDepAtom::ConstPointer a) : + _atom(a) +{ +} + diff --git a/paludis/block_dep_atom.hh b/paludis/block_dep_atom.hh new file mode 100644 index 000000000..8709bcfbb --- /dev/null +++ b/paludis/block_dep_atom.hh @@ -0,0 +1,67 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_BLOCK_DEP_ATOM_HH +#define PALUDIS_GUARD_PALUDIS_BLOCK_DEP_ATOM_HH 1 + +#include <paludis/dep_atom.hh> +#include <paludis/package_dep_atom.hh> + +/** \file + * Declarations for the BlockDepAtom class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * A BlockDepAtom represents a block on a package name (for example, + * 'app-editors/vim'), possibly with associated version and SLOT + * restrictions. + * + * \ingroup DepResolver + */ + class BlockDepAtom : public DepAtom, + public Visitable<BlockDepAtom, DepAtomVisitor> + { + private: + PackageDepAtom::ConstPointer _atom; + + public: + /** + * Constructor, with blocking atom. + */ + BlockDepAtom(PackageDepAtom::ConstPointer atom); + + /** + * Fetch the atom we're blocking. + */ + PackageDepAtom::ConstPointer blocked_atom() const + { + return _atom; + } + + typedef CountedPtr<BlockDepAtom, count_policy::InternalCountTag> Pointer; + typedef CountedPtr<const BlockDepAtom, count_policy::InternalCountTag> ConstPointer; + }; +} + + +#endif diff --git a/paludis/block_error.cc b/paludis/block_error.cc new file mode 100644 index 000000000..6099be223 --- /dev/null +++ b/paludis/block_error.cc @@ -0,0 +1,10 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "block_error.hh" + +using namespace paludis; + +BlockError::BlockError(const std::string & msg) throw () : + DepListError("Block: " + msg) +{ +} diff --git a/paludis/block_error.hh b/paludis/block_error.hh new file mode 100644 index 000000000..6b16c2a47 --- /dev/null +++ b/paludis/block_error.hh @@ -0,0 +1,38 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_BLOCK_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_BLOCK_ERROR_HH 1 + +#include <paludis/dep_list_error.hh> + +namespace paludis +{ + /** + * Thrown if a block is encountered. + */ + class BlockError : public DepListError + { + public: + BlockError(const std::string & msg) throw (); + }; +} + +#endif diff --git a/paludis/category_name_part.cc b/paludis/category_name_part.cc new file mode 100644 index 000000000..7f84ca1d9 --- /dev/null +++ b/paludis/category_name_part.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "category_name_part.hh" + diff --git a/paludis/category_name_part.hh b/paludis/category_name_part.hh new file mode 100644 index 000000000..451239534 --- /dev/null +++ b/paludis/category_name_part.hh @@ -0,0 +1,44 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_CATEGORY_NAME_PART_HH +#define PALUDIS_GUARD_PALUDIS_CATEGORY_NAME_PART_HH 1 + +#include <paludis/validated.hh> +#include <paludis/category_name_part_validator.hh> +#include <string> + +/** \file + * Declaration for the CategoryNamePart class. + * + * \ingroup Database + */ + +namespace paludis +{ + /** + * A CategoryNamePart holds a std::string that is a valid name for the + * category part of a QualifiedPackageName. + * + * \ingroup Database + */ + typedef Validated<std::string, CategoryNamePartValidator> CategoryNamePart; +} + +#endif diff --git a/paludis/category_name_part_collection.cc b/paludis/category_name_part_collection.cc new file mode 100644 index 000000000..360cea35c --- /dev/null +++ b/paludis/category_name_part_collection.cc @@ -0,0 +1,31 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "category_name_part_collection.hh" + +using namespace paludis; + +CategoryNamePartCollection::CategoryNamePartCollection() +{ +} + +CategoryNamePartCollection::~CategoryNamePartCollection() +{ +} + diff --git a/paludis/category_name_part_collection.hh b/paludis/category_name_part_collection.hh new file mode 100644 index 000000000..040d5055a --- /dev/null +++ b/paludis/category_name_part_collection.hh @@ -0,0 +1,48 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_CATEGORY_NAME_PART_COLLECTION_HH +#define PALUDIS_GUARD_PALUDIS_CATEGORY_NAME_PART_COLLECTION_HH 1 + +#include <paludis/category_name_part.hh> +#include <paludis/sorted_collection.hh> + +namespace paludis +{ + /** + * Holds a set of CategoryNamePart instances. + * + * \ingroup Database + */ + class CategoryNamePartCollection : public SortedCollection<CategoryNamePart> + { + public: + /** + * Constructor. + */ + CategoryNamePartCollection(); + + /** + * Destructor. + */ + virtual ~CategoryNamePartCollection(); + }; +} + +#endif diff --git a/paludis/category_name_part_error.cc b/paludis/category_name_part_error.cc new file mode 100644 index 000000000..4aded7bbc --- /dev/null +++ b/paludis/category_name_part_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "category_name_part_error.hh" + +using namespace paludis; + +CategoryNamePartError::CategoryNamePartError(const std::string & name) throw () : + NameError(name, "category name part") +{ +} + diff --git a/paludis/category_name_part_error.hh b/paludis/category_name_part_error.hh new file mode 100644 index 000000000..98234735f --- /dev/null +++ b/paludis/category_name_part_error.hh @@ -0,0 +1,52 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_CATEGORY_NAME_PART_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_CATEGORY_NAME_PART_ERROR_HH 1 + +#include <paludis/name_error.hh> +#include <string> + +/** \file + * Declaration for the CategoryNamePartError exception. + * + * \ingroup Exception + * \ingroup Database + */ + +namespace paludis +{ + /** + * A CategoryNamePartError is thrown if an invalid value is assigned to + * a CategoryNamePart. + * + * \ingroup Exception + * \ingroup Database + */ + class CategoryNamePartError : public NameError + { + public: + /** + * Constructor. + */ + CategoryNamePartError(const std::string & name) throw (); + }; +} + +#endif diff --git a/paludis/category_name_part_validator.cc b/paludis/category_name_part_validator.cc new file mode 100644 index 000000000..e5e7bec0a --- /dev/null +++ b/paludis/category_name_part_validator.cc @@ -0,0 +1,49 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "category_name_part_validator.hh" +#include "category_name_part_error.hh" + +using namespace paludis; + +void +CategoryNamePartValidator::validate(const std::string & s) +{ + /* this gets called a lot, make it fast */ + + static const std::string allowed_chars( + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-+_"); + + do + { + if (s.empty()) + break; + + if (std::string::npos != s.find_first_not_of(allowed_chars)) + break; + + return; + + } while (false); + + Context c("When validating category name '" + s + "':"); + throw CategoryNamePartError(s); +} diff --git a/paludis/category_name_part_validator.hh b/paludis/category_name_part_validator.hh new file mode 100644 index 000000000..f74cf95e5 --- /dev/null +++ b/paludis/category_name_part_validator.hh @@ -0,0 +1,51 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_CATEGORY_NAME_PART_VALIDATOR_HH +#define PALUDIS_GUARD_PALUDIS_CATEGORY_NAME_PART_VALIDATOR_HH 1 + +#include <string> +#include <paludis/instantiation_policy.hh> + +/** \file + * Declaration for the CategoryNamePartValidator class. + * + * \ingroup Database + */ + +namespace paludis +{ + /** + * A CategoryNamePartValidator handles validation rules for the value + * of a CategoryNamePart. + * + * \ingroup Database + */ + struct CategoryNamePartValidator : + private InstantiationPolicy<CategoryNamePartValidator, instantiation_method::NonInstantiableTag> + { + /** + * If the parameter is not a valid value for a CategoryNamePart, + * throw a CategoryNamePartError. + */ + static void validate(const std::string &); + }; +} + +#endif diff --git a/paludis/circular_dependency_error.cc b/paludis/circular_dependency_error.cc new file mode 100644 index 000000000..4d7d50f32 --- /dev/null +++ b/paludis/circular_dependency_error.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "circular_dependency_error.hh" + diff --git a/paludis/circular_dependency_error.hh b/paludis/circular_dependency_error.hh new file mode 100644 index 000000000..fd4111bb2 --- /dev/null +++ b/paludis/circular_dependency_error.hh @@ -0,0 +1,46 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_CIRCULAR_DEPENDENCY_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_CIRCULAR_DEPENDENCY_ERROR_HH 1 + +#include <paludis/dep_list_error.hh> +#include <paludis/join.hh> + +namespace paludis +{ + /** + * Thrown if a circular dependency is encountered. + */ + class CircularDependencyError : public DepListError + { + public: + /** + * Constructor, from a sequence of the items causing the circular + * dependency. + */ + template <typename I_> + CircularDependencyError(I_ begin, const I_ end) throw () : + DepListError("Circular dependency: " + join(begin, end, " -> ")) + { + } + }; +} + +#endif diff --git a/paludis/comparison_policy.cc b/paludis/comparison_policy.cc new file mode 100644 index 000000000..c12356641 --- /dev/null +++ b/paludis/comparison_policy.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "comparison_policy.hh" + diff --git a/paludis/comparison_policy.hh.m4 b/paludis/comparison_policy.hh.m4 new file mode 100644 index 000000000..b33f2f847 --- /dev/null +++ b/paludis/comparison_policy.hh.m4 @@ -0,0 +1,406 @@ +#if 0 +ifdef(`__gnu__',`',`errprint(`This is not GNU m4... +')m4exit(1)') include(`misc/generated-file.txt') +dnl vim: set ft=cpp et sw=4 sts=4 : +#endif + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_COMPARISON_POLICY_HH +#define PALUDIS_GUARD_PALUDIS_COMPARISON_POLICY_HH 1 + +namespace paludis +{ + /** + * Comparison modes for paludis::ComparisonPolicy. + */ + namespace comparison_mode + { + /** + * No comparisons can be made. + */ + struct NoComparisonTag + { + }; + + /** + * Comparisons can be made via operator== and operator!=. + */ + struct EqualityComparisonTag + { + }; + + /** + * The full range of comparison operators is available. + */ + struct FullComparisonTag + { + }; + } + + /** + * Comparison methods for paludis::ComparisonPolicy. + */ + namespace comparison_method + { + /** + * Comparisons are done via a member of type MemberType_. + */ + template <typename MemberType_> + struct CompareByMemberTag + { + }; + + /** + * Comparisons are done by a member function that returns an integer + * less than zero (less than), equal to zero (equal to) or greater than + * zero (greater than). + */ + struct CompareByMemberComparisonFunctionTag + { + }; + + + /** + * Comparisons are done via a member function that returns an item of + * type MemberType_. + */ + template <typename MemberType_> + struct CompareByMemberFetchFunctionTag + { + }; + } + +#ifdef DOXYGEN + /** + * ComparisonPolicy specifies the availabillity of comparison methods and + * the strategy used to do comparisons. + */ + template <typename OurType_, typename ComparisonModeTag_, typename ComparisonMethodTag_> + struct ComparisonPolicy + { + }; +#else + template <typename OurType_, typename ComparisonModeTag_, typename ComparisonMethodTag_> + struct ComparisonPolicy; +#endif + + /** + * ComparisonPolicy: specialisation for NoComparisonTag. + */ + template <typename OurType_, typename ComparisonMethodTag_> + class ComparisonPolicy<OurType_, comparison_mode::NoComparisonTag, ComparisonMethodTag_> + { + public: + /// Our comparison mode. + typedef comparison_mode::NoComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef ComparisonMethodTag_ ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + }; + + /** + * ComparisonPolicy: specialisation for EqualityComparisonTag + + * CompareByMemberTag. + */ + template <typename OurType_, typename MemberType_> + class ComparisonPolicy<OurType_, comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberTag<MemberType_> > + { + private: + const MemberType_ OurType_::* const _v; + + public: + /// Our comparison mode. + typedef comparison_mode::EqualityComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef comparison_method::CompareByMemberTag<MemberType_> ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + + /// Constructor. + ComparisonPolicy(const MemberType_ OurType_::* const v) : + _v(v) + { + } + + /// Copy constructor. + ComparisonPolicy(const ComparisonPolicy & other) : + _v(other._v) + { + } + +define(`make_operator', ` + /// $1 operator. + bool operator$1 (const OurType_ & other) const + { + return static_cast<const OurType_ *>(this)->*_v $1 other.*( + (static_cast<const ComparisonPolicyType *>(&other))->_v); + } +') +make_operator(`==') +make_operator(`!=') + + }; + + /** + * ComparisonPolicy: specialisation for EqualityComparisonTag + + * CompareByMemberComparisonFunctionTag. + */ + template <typename OurType_> + class ComparisonPolicy<OurType_, comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberComparisonFunctionTag> + { + private: + bool (OurType_::* const _v)(const OurType_ &) const; + + public: + /// Our comparison mode. + typedef comparison_mode::EqualityComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef comparison_method::CompareByMemberComparisonFunctionTag ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + + /// Constructor. + ComparisonPolicy(bool (OurType_::* const v)(const OurType_ &) const) : + _v(v) + { + } + + /// Copy constructor. + ComparisonPolicy(const ComparisonPolicy & other) : + _v(other._v) + { + } + + /// Equal operator. + bool operator== (const OurType_ & other) const + { + return (static_cast<const OurType_ *>(this)->*_v)(other); + } + + /// Not equal operator. + bool operator!= (const OurType_ & other) const + { + return ! (static_cast<const OurType_ *>(this)->*_v)(other); + } + }; + + /** + * ComparisonPolicy: specialisation for FullComparisonTag + + * CompareByMemberTag. + */ + template <typename OurType_, typename MemberType_> + class ComparisonPolicy<OurType_, comparison_mode::FullComparisonTag, + comparison_method::CompareByMemberTag<MemberType_> > + { + private: + const MemberType_ OurType_::* const _v; + + public: + /// Our comparison mode. + typedef comparison_mode::FullComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef comparison_method::CompareByMemberTag<MemberType_> ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + + /// Constructor. + ComparisonPolicy(const MemberType_ OurType_::* const v) : + _v(v) + { + } + + /// Copy constructor. + ComparisonPolicy(const ComparisonPolicy & other) : + _v(other._v) + { + } + +define(`make_operator', ` + /// $1 operator. + bool operator$1 (const OurType_ & other) const + { + return static_cast<const OurType_ *>(this)->*_v $1 other.*( + (static_cast<const ComparisonPolicyType *>(&other))->_v); + } +') +make_operator(`==') +make_operator(`!=') +make_operator(`<=') +make_operator(`>=') +make_operator(`<') +make_operator(`>') + + }; + + /** + * ComparisonPolicy: specialisation for FullComparisonTag + + * CompareByMemberComparisonFunctionTag. + */ + template <typename OurType_> + class ComparisonPolicy<OurType_, comparison_mode::FullComparisonTag, + comparison_method::CompareByMemberComparisonFunctionTag> + { + private: + int (OurType_::* const _v)(const OurType_ &) const; + + public: + /// Our comparison mode. + typedef comparison_mode::FullComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef comparison_method::CompareByMemberComparisonFunctionTag ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + + /// Constructor. + ComparisonPolicy(int (OurType_::* v)(const OurType_ &) const) : + _v(v) + { + } + + /// Copy constructor. + ComparisonPolicy(const ComparisonPolicy & other) : + _v(other._v) + { + } + +define(`make_operator', ` + /// $1 operator. + bool operator$1 (const OurType_ & other) const + { + return (static_cast<const OurType_ *>(this)->*_v)(other) $1 0; + } +') +make_operator(`==') +make_operator(`!=') +make_operator(`<=') +make_operator(`>=') +make_operator(`<') +make_operator(`>') + + }; + + /** + * ComparisonPolicy: specialisation for EqualityComparisonTag + + * CompareByMemberFetchFunctionTag. + */ + template <typename OurType_, typename MemberType_> + class ComparisonPolicy<OurType_, comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberFetchFunctionTag<MemberType_> > + { + private: + MemberType_ (OurType_::* const _v)() const; + + public: + /// Our comparison mode. + typedef comparison_mode::EqualityComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef comparison_method::CompareByMemberFetchFunctionTag<MemberType_> ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + + /// Constructor. + ComparisonPolicy(MemberType_ (OurType_::* const v)() const) : + _v(v) + { + } + + /// Copy constructor. + ComparisonPolicy(const ComparisonPolicy & other) : + _v(other._v) + { + } + +define(`make_operator', ` + /// $1 operator. + bool operator$1 (const OurType_ & other) const + { + return (static_cast<const OurType_ *>(this)->*_v)() $1 (other.*other._v)(); + } +') +make_operator(`==') +make_operator(`!=') + }; + + /** + * ComparisonPolicy: specialisation for FullComparisonTag + + * CompareByMemberFetchFunctionTag. + */ + template <typename OurType_, typename MemberType_> + class ComparisonPolicy<OurType_, comparison_mode::FullComparisonTag, + comparison_method::CompareByMemberFetchFunctionTag<MemberType_> > + { + private: + MemberType_ (OurType_::* const _v)() const; + + public: + /// Our comparison mode. + typedef comparison_mode::FullComparisonTag ComparisonPolicyModeTag; + + /// Our comparison method. + typedef comparison_method::CompareByMemberFetchFunctionTag<MemberType_> ComparisonPolicyMethodTag; + + /// Our comparison policy. + typedef ComparisonPolicy<OurType_, ComparisonPolicyModeTag, ComparisonPolicyMethodTag> ComparisonPolicyType; + + /// Constructor. + ComparisonPolicy(MemberType_ (OurType_::* const v)() const) : + _v(v) + { + } + + /// Copy constructor. + ComparisonPolicy(const ComparisonPolicy & other) : + _v(other._v) + { + } + +define(`make_operator', ` + /// $1 operator. + bool operator$1 (const OurType_ & other) const + { + return ((static_cast<const OurType_ *>(this)->*_v)()) $1 + ((other.*(static_cast<const OurType_ *>(&other)->_v))()); + } +') +make_operator(`==') +make_operator(`!=') +make_operator(`>=') +make_operator(`<=') +make_operator(`>') +make_operator(`<') + + }; +} + +#endif diff --git a/paludis/comparison_policy_TEST.cc b/paludis/comparison_policy_TEST.cc new file mode 100644 index 000000000..1bdbe1ca7 --- /dev/null +++ b/paludis/comparison_policy_TEST.cc @@ -0,0 +1,39 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "comparison_policy.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace paludis; +using namespace test; + +/// \todo + +namespace test_cases +{ + struct ComparisonTest : TestCase + { + ComparisonTest() : TestCase("comparison") { } + + void run() + { + } + } test_comparison; +} diff --git a/paludis/composite_dep_atom.cc b/paludis/composite_dep_atom.cc new file mode 100644 index 000000000..c6b0ca7b7 --- /dev/null +++ b/paludis/composite_dep_atom.cc @@ -0,0 +1,32 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "composite_dep_atom.hh" + +using namespace paludis; + +CompositeDepAtom::CompositeDepAtom() +{ +} + +void +CompositeDepAtom::add_child(DepAtom::ConstPointer c) +{ + _children.push_back(c); +} diff --git a/paludis/composite_dep_atom.hh b/paludis/composite_dep_atom.hh new file mode 100644 index 000000000..e4c20ccc8 --- /dev/null +++ b/paludis/composite_dep_atom.hh @@ -0,0 +1,85 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_COMPOSITE_DEP_ATOM_HH +#define PALUDIS_GUARD_PALUDIS_COMPOSITE_DEP_ATOM_HH 1 + +#include <paludis/dep_atom.hh> +#include <paludis/counted_ptr.hh> +#include <list> + +/** \file + * Declarations for the CompositeDepAtom class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * Class for dependency atoms that have a number of child dependency + * atoms. + * + * \ingroup DepResolver + */ + class CompositeDepAtom : public DepAtom, + public virtual Composite<DepAtom, CompositeDepAtom> + { + private: + std::list<DepAtom::ConstPointer> _children; + + protected: + /** + * Constructor. + */ + CompositeDepAtom(); + + public: + /** + * Append a child to our collection. + */ + virtual void add_child(DepAtom::ConstPointer); + + /** + * Iterator for iterating over our children. + */ + typedef std::list<DepAtom::ConstPointer>::const_iterator Iterator; + + /** + * Iterator to the start of our children. + */ + Iterator begin() const + { + return _children.begin(); + } + + /** + * Iterator to past the end of our children. + */ + Iterator end() const + { + return _children.end(); + } + + typedef CountedPtr<CompositeDepAtom, count_policy::InternalCountTag> Pointer; + typedef CountedPtr<const CompositeDepAtom, count_policy::InternalCountTag> ConstPointer; + }; +} + +#endif diff --git a/paludis/composite_pattern.cc b/paludis/composite_pattern.cc new file mode 100644 index 000000000..986fb5540 --- /dev/null +++ b/paludis/composite_pattern.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "composite_pattern.hh" + diff --git a/paludis/composite_pattern.hh b/paludis/composite_pattern.hh new file mode 100644 index 000000000..fecb47c44 --- /dev/null +++ b/paludis/composite_pattern.hh @@ -0,0 +1,64 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_COMPOSITE_PATTERN_HH +#define PALUDIS_GUARD_PALUDIS_COMPOSITE_PATTERN_HH 1 + +/** \file + * Declarations for the Composite template class. + * + * \ingroup Utility + */ + +namespace paludis +{ + /** + * A Composite class represents both a class and a collection of + * child instances of the same class. + */ + template <typename ChildClass_, typename CompositeClass_ = ChildClass_> + class Composite + { + private: + mutable CompositeClass_ * _composite; + + protected: + /** + * Constructor. + */ + Composite() : + _composite(0) + { + } + + public: + /** + * Fetch a CompositeClass_ representation of ourself, or 0 if we + * are not composite. + */ + CompositeClass_ * get_composite() const + { + if (0 == _composite) + _composite = & dynamic_cast<CompositeClass_>(*this); + return _composite; + } + }; +} + +#endif diff --git a/paludis/composite_visitor_pattern-impl.hh b/paludis/composite_visitor_pattern-impl.hh new file mode 100644 index 000000000..d3c1b0cde --- /dev/null +++ b/paludis/composite_visitor_pattern-impl.hh @@ -0,0 +1,41 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_COMPOSITE_VISITOR_PATTERN_IMPL_HH +#define PALUDIS_GUARD_PALUDIS_COMPOSITE_VISITOR_PATTERN_IMPL_HH 1 + +#include <paludis/visitor_pattern-impl.hh> + +namespace paludis +{ + template <typename OurType_, typename CNodeType_> + void + VisitsComposite<OurType_, CNodeType_>::visit(const CNodeType_ * const n) + { + enter(n); + + typename CNodeType_::Iterator i(n->begin()), e(n->end()); + for ( ; i != e ; ++i) + (*i)->accept(static_cast<OurType_ *>(this)); + + leave(n); + } +} + +#endif diff --git a/paludis/composite_visitor_pattern.cc b/paludis/composite_visitor_pattern.cc new file mode 100644 index 000000000..08b162aee --- /dev/null +++ b/paludis/composite_visitor_pattern.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "composite_visitor_pattern.hh" +#include "composite_visitor_pattern-impl.hh" diff --git a/paludis/composite_visitor_pattern.hh b/paludis/composite_visitor_pattern.hh new file mode 100644 index 000000000..5d768952f --- /dev/null +++ b/paludis/composite_visitor_pattern.hh @@ -0,0 +1,55 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_COMPOSITE_VISITOR_PATTERN_HH +#define PALUDIS_GUARD_PALUDIS_COMPOSITE_VISITOR_PATTERN_HH 1 + +#include <paludis/visitor_pattern.hh> + +namespace paludis +{ + /** + * Declares that a class can visit a node of type NodeType_, which is + * a composite node, and that it should use enter and leave rather than + * visit. + * + * \ingroup Utility + */ + template <typename OurType_, typename CNodeType_> + class VisitsComposite : public virtual Visits<CNodeType_> + { + public: + /** + * Implement visit to call enter, then our children, then leave. + */ + virtual void visit(const CNodeType_ * const n); + + /** + * Interface: enter a node. + */ + virtual void enter(const CNodeType_ * const n) = 0; + + /** + * Interface: leave a node. + */ + virtual void leave(const CNodeType_ * const n) = 0; + }; +} + +#endif diff --git a/paludis/config_file.cc b/paludis/config_file.cc new file mode 100644 index 000000000..f63ab06be --- /dev/null +++ b/paludis/config_file.cc @@ -0,0 +1,64 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "config_file.hh" +#include "config_file_error.hh" +#include "strip.hh" + +using namespace paludis; + +ConfigFile::ConfigFile(std::istream * const stream) : + _stream(stream), + _has_lines(false) +{ +} + +void +ConfigFile::need_lines() const +{ + if (_has_lines) + return; + + std::string line; + while (std::getline(*_stream, line)) + { + normalise_line(line); + if (skip_line(line)) + continue; + accept_line(line); + } + if (! _stream->eof()) + throw ConfigFileError("Error reading from file"); + + _has_lines = true; +} + +void +ConfigFile::normalise_line(std::string & s) const +{ + s = strip_leading(strip_trailing(s, " \t\n"), " \t\n"); +} + +bool +ConfigFile::skip_line(const std::string & s) const +{ + return (s.empty() || '#' == s.at(0)); +} + diff --git a/paludis/config_file.hh b/paludis/config_file.hh new file mode 100644 index 000000000..198891ff2 --- /dev/null +++ b/paludis/config_file.hh @@ -0,0 +1,92 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_CONFIG_FILE_HH +#define PALUDIS_GUARD_PALUDIS_CONFIG_FILE_HH 1 + +#include <paludis/instantiation_policy.hh> +#include <istream> +#include <list> +#include <string> + +/** \file + * Declarations for the ConfigFile class. + * + * \ingroup ConfigFile + */ + +namespace paludis +{ + /** + * A ConfigFile is a file containing one entry per line, with lines + * starting with a # being ignored and leading and trailing whitespace + * being discarded. + * + * \ingroup ConfigFile + */ + class ConfigFile : + paludis::InstantiationPolicy<ConfigFile, instantiation_method::NonCopyableTag> + { + private: + std::istream * const _stream; + + mutable bool _has_lines; + + protected: + /** + * In-place normalise a line. By default, trims leading and + * trailing whitespace. Child classes may override. + */ + virtual void normalise_line(std::string &) const; + + /** + * Return whether to skip a line. By default, skips on blank + * lines and lines starting with a #. Child classes may + * override. This is called on a normalised line, not a raw + * string. + */ + virtual bool skip_line(const std::string &) const; + + /** + * Accept a normalised line that is not to be skipped. + */ + virtual void accept_line(const std::string &) const = 0; + + /** + * If we have not done so already, read in our lines. + */ + void need_lines() const; + + /** + * Constructor. + */ + ConfigFile(std::istream * const stream); + + public: + /** + * Destructor. + */ + virtual ~ConfigFile() + { + } + }; +} + +#endif diff --git a/paludis/config_file_TEST.cc b/paludis/config_file_TEST.cc new file mode 100644 index 000000000..1371a76ff --- /dev/null +++ b/paludis/config_file_TEST.cc @@ -0,0 +1,90 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "config_file.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <sstream> +#include <vector> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for config_file.hh . + * + * \ingroup Test + * \ingroup ConfigFile + */ + +#ifndef DOXYGEN +class TestFile : protected ConfigFile +{ + public: + TestFile(std::istream * const stream) : + ConfigFile(stream) + { + need_lines(); + } + + mutable std::vector<std::string> lines; + + protected: + void accept_line(const std::string & s) const + { + lines.push_back(s); + } +}; +#endif + +namespace test_cases +{ + /** + * \test Test ConfigFile. + * + * \ingroup Test + */ + struct ConfigFileTest : TestCase + { + ConfigFileTest() : TestCase("config file") { } + + void run() + { + std::stringstream s; + s << "one" << std::endl; + s << " two \t " << std::endl; + s << " \t " << std::endl; + s << "" << std::endl; + s << "three" << std::endl; + s << "# blah" << std::endl; + s << " # blah" << std::endl; + s << "#" << std::endl; + s << " # \t " << std::endl; + s << "four four" << std::endl; + TestFile f(&s); + TEST_CHECK_EQUAL(f.lines.size(), 4); + TEST_CHECK_EQUAL(f.lines.at(0), "one"); + TEST_CHECK_EQUAL(f.lines.at(1), "two"); + TEST_CHECK_EQUAL(f.lines.at(2), "three"); + TEST_CHECK_EQUAL(f.lines.at(3), "four four"); + } + } test_config_file; +} + diff --git a/paludis/config_file_error.cc b/paludis/config_file_error.cc new file mode 100644 index 000000000..1dd881b84 --- /dev/null +++ b/paludis/config_file_error.cc @@ -0,0 +1,29 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "config_file_error.hh" + +using namespace paludis; + +ConfigFileError::ConfigFileError(const std::string & message) throw () : + Exception("Config file error: " + message) +{ +} + diff --git a/paludis/config_file_error.hh b/paludis/config_file_error.hh new file mode 100644 index 000000000..f14534cea --- /dev/null +++ b/paludis/config_file_error.hh @@ -0,0 +1,44 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_CONFIG_FILE_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_CONFIG_FILE_ERROR_HH 1 + +#include <paludis/exception.hh> + +namespace paludis +{ + /** + * Thrown if an error occurs when reading a ConfigFile. + * + * \ingroup Exception + * \ingroup ConfigFile + */ + class ConfigFileError : public Exception + { + public: + /** + * Constructor. + */ + ConfigFileError(const std::string & message) throw (); + }; +} + +#endif diff --git a/paludis/container_entry.cc b/paludis/container_entry.cc new file mode 100644 index 000000000..99bd3fb94 --- /dev/null +++ b/paludis/container_entry.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "container_entry.hh" + diff --git a/paludis/container_entry.hh b/paludis/container_entry.hh new file mode 100644 index 000000000..bbab40232 --- /dev/null +++ b/paludis/container_entry.hh @@ -0,0 +1,66 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_CONTAINER_ENTRY_HH +#define PALUDIS_GUARD_PALUDIS_CONTAINER_ENTRY_HH 1 + +#include <list> + +namespace paludis +{ + /** + * Hold an entry in a container for as long as our ContainerEntry instance + * is in scope (RAII). + */ + template <typename Container_> + struct ContainerEntry; + + /** + * Hold an entry in a container for as long as our ContainerEntry instance + * is in scope (RAII, partial specialisation for std::list). + */ + template <typename Item_> + class ContainerEntry<std::list<Item_> > + { + private: + std::list<Item_> * const _list; + + typename std::list<Item_>::iterator _item; + + public: + /** + * Constructor. + */ + ContainerEntry(std::list<Item_> * const list, const Item_ & item) : + _list(list), + _item(list->insert(list->begin(), item)) + { + } + + /** + * Destructor. + */ + ~ContainerEntry() + { + _list->erase(_item); + } + }; +} + +#endif diff --git a/paludis/container_entry_TEST.cc b/paludis/container_entry_TEST.cc new file mode 100644 index 000000000..91a74dbd5 --- /dev/null +++ b/paludis/container_entry_TEST.cc @@ -0,0 +1,60 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 <test/test_framework.hh> +#include <test/test_runner.hh> +#include "container_entry.hh" +#include <algorithm> + +using namespace test; +using namespace paludis; + +namespace test_cases +{ + struct ContainerEntryListTest : TestCase + { + ContainerEntryListTest() : TestCase("list") { } + + void run() + { + std::list<int> list; + TEST_CHECK(list.empty()); + { + ContainerEntry<std::list<int> > e1(&list, 5); + TEST_CHECK(list.begin() != list.end()); + TEST_CHECK_EQUAL(std::distance(list.begin(), list.end()), 1); + TEST_CHECK(list.end() != std::find(list.begin(), list.end(), 5)); + + { + ContainerEntry<std::list<int> > e2(&list, 4); + TEST_CHECK(list.begin() != list.end()); + TEST_CHECK_EQUAL(std::distance(list.begin(), list.end()), 2); + TEST_CHECK(list.end() != std::find(list.begin(), list.end(), 5)); + TEST_CHECK(list.end() != std::find(list.begin(), list.end(), 4)); + } + + TEST_CHECK(list.begin() != list.end()); + TEST_CHECK_EQUAL(std::distance(list.begin(), list.end()), 1); + TEST_CHECK(list.end() != std::find(list.begin(), list.end(), 5)); + } + TEST_CHECK(list.empty()); + } + } test_container_entry_list; +} + diff --git a/paludis/counted_ptr.cc b/paludis/counted_ptr.cc new file mode 100644 index 000000000..eb9f78812 --- /dev/null +++ b/paludis/counted_ptr.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "counted_ptr.hh" + diff --git a/paludis/counted_ptr.hh b/paludis/counted_ptr.hh new file mode 100644 index 000000000..51cac27dc --- /dev/null +++ b/paludis/counted_ptr.hh @@ -0,0 +1,540 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_COUNTED_PTR_HH +#define PALUDIS_GUARD_PALUDIS_COUNTED_PTR_HH 1 + +#include <paludis/attributes.hh> +#include <paludis/comparison_policy.hh> +#include <paludis/counted_ptr_error.hh> + +/** \file + * Declaration for the CountedPtr template class. + * + * \ingroup Pointer + */ + +namespace paludis +{ + /** + * Contains CountedPtr count policies. + * + * \ingroup Pointer + */ + namespace count_policy + { + /** + * CountedPtr policy: reference counts are stored separately. + * + * \ingroup Pointer + */ + struct ExternalCountTag + { + }; + + /** + * CountedPtr policy: reference counts are stored by the class via the + * Counted subclass. + * + * \ingroup Pointer + */ + struct InternalCountTag + { + }; + } + + /** + * Contains CountedPtr dereference policies. + * + * \ingroup Pointer + */ + namespace dereference_policy + { + /** + * CountedPtr dereferences are not checked. + * + * \ingroup Pointer + */ + struct UncheckedDereferenceTag + { + }; + + /** + * CountedPtr dereferences are checked, and a CountedPtrError is + * thrown for 0 dereferences. + * + * \ingroup Pointer + */ + struct CheckedDereferenceTag + { + }; + } + + /** + * CountedPtr internals. + * + * \ingroup Pointer + */ + namespace counted_ptr_internals + { + /** + * Base class for CountedPtr. + */ + template <typename T_, typename DereferencePolicy_> + class CountedPtrBase; + + /** + * Base class for CountedPtr (specialisation for UncheckedDereferenceTag). + */ + template <typename T_> + class CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag> : + public ComparisonPolicy<CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag>, + comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberTag<T_ *> > + { + private: + CountedPtrBase(const CountedPtrBase & other); + + const CountedPtrBase & operator= (const CountedPtrBase & other); + + protected: + /** + * Pointer to our data. + */ + T_ * _ptr; + + CountedPtrBase(T_ * ptr) : + ComparisonPolicy<CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag>, + comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberTag<T_ *> >( + &CountedPtrBase::_ptr), + _ptr(ptr) + { + } + + ~CountedPtrBase() + { + } + + public: + /** + * Dereference operator (const). + */ + inline const T_ & operator* () const PALUDIS_ATTRIBUTE((pure)); + + /** + * Dereference to member operator (const). + */ + inline const T_ * operator-> () const PALUDIS_ATTRIBUTE((pure)); + + /** + * Dereference operator (non const). + */ + T_ & operator* () PALUDIS_ATTRIBUTE((pure)); + + /** + * Dereference to member operator (non const). + */ + T_ * operator-> () PALUDIS_ATTRIBUTE((pure)); + + /** + * Not null? + */ + operator bool() const + { + return _ptr; + } + + /** + * Fetch our raw pointer. + */ + T_ * raw_pointer() const + { + return _ptr; + } + }; + + template <typename T_> + const T_ & CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag>::operator* () const + { + return *_ptr; + } + + template <typename T_> + const T_ * CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag>::operator-> () const + { + return _ptr; + } + + template <typename T_> + T_ & CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag>::operator* () + { + return *_ptr; + } + + template <typename T_> + T_ * CountedPtrBase<T_, dereference_policy::UncheckedDereferenceTag>::operator-> () + { + return _ptr; + } + /** + * Base class for CountedPtr (specialisation for CheckedDereferenceTag). + */ + template <typename T_> + class CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag> : + public ComparisonPolicy<CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag>, + comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberTag<T_ *> > + { + private: + CountedPtrBase(const CountedPtrBase & other); + + const CountedPtrBase & operator= (const CountedPtrBase & other); + + protected: + /** + * Pointer to our data. + */ + T_ * _ptr; + + CountedPtrBase(T_ * ptr) : + ComparisonPolicy<CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag>, + comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberTag<T_ *> >( + &CountedPtrBase::_ptr), + _ptr(ptr) + { + } + + ~CountedPtrBase() + { + } + + public: + /** + * Dereference operator (const). + */ + inline const T_ & operator* () const PALUDIS_ATTRIBUTE((pure)); + + /** + * Dereference to member operator (const). + */ + inline const T_ * operator-> () const PALUDIS_ATTRIBUTE((pure)); + + /** + * Dereference operator (non const). + */ + T_ & operator* () PALUDIS_ATTRIBUTE((pure)); + + /** + * Dereference to member operator (non const). + */ + T_ * operator-> () PALUDIS_ATTRIBUTE((pure)); + + /** + * Not null? + */ + operator bool() const + { + return _ptr; + } + + /** + * Fetch our raw pointer. + */ + T_ * raw_pointer() const + { + return _ptr; + } + }; + + template <typename T_> + const T_ & CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag>::operator* () const + { + if (0 == _ptr) + throw CountedPtrError(); + return *_ptr; + } + + template <typename T_> + const T_ * CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag>::operator-> () const + { + if (0 == _ptr) + throw CountedPtrError(); + return _ptr; + } + + template <typename T_> + T_ & CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag>::operator* () + { + if (0 == _ptr) + throw CountedPtrError(); + return *_ptr; + } + + template <typename T_> + T_ * CountedPtrBase<T_, dereference_policy::CheckedDereferenceTag>::operator-> () + { + if (0 == _ptr) + throw CountedPtrError(); + return _ptr; + } + } + + /** + * Reference counted pointer class. + * + * \ingroup Pointer + */ + template <typename T_, typename CountPolicy_ = count_policy::InternalCountTag, + typename DereferencePolicy_ = dereference_policy::UncheckedDereferenceTag> + class CountedPtr; + + /** + * Base for an internal counted class. + * + * \ingroup Pointer + */ + template <typename T_, typename DereferencePolicy_ = dereference_policy::UncheckedDereferenceTag> + class InternalCounted; + + /** + * Reference counted pointer class (specialisation for ExternalCountTag). + * + * \ingroup Pointer + */ + template <typename T_, typename DereferencePolicy_> + class CountedPtr<T_, count_policy::ExternalCountTag, DereferencePolicy_> : + public counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_> + { + private: + unsigned * _ref_count; + + public: + /** + * Constructor, from a raw pointer. + */ + explicit CountedPtr(T_ * const ptr) : + counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_>(ptr), + _ref_count(new unsigned(1)) + { + } + + /** + * Constructor, from another CountedPtr. + */ + CountedPtr(const CountedPtr & other) : + counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_>(other.raw_pointer()), + _ref_count(other._ref_count) + { + ++*_ref_count; + } + + /** + * Constructor, from another CountedPtr of a descendent of our + * data's class. + */ + template <typename O_> + CountedPtr(const CountedPtr<O_, count_policy::ExternalCountTag> & other) : + counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_>(other._ptr), + _ref_count(other.reference_count_pointer()) + { + ++*_ref_count; + } + + /** + * Destructor. + */ + ~CountedPtr() + { + if (0 == --(*_ref_count)) + { + delete this->_ptr; + delete _ref_count; + } + } + + /** + * Assignment, from another CountedPtr. + */ + const CountedPtr & operator= (const CountedPtr & other) + { + if (other._ptr != this->_ptr) + { + if (0 == --*_ref_count) + { + delete this->_ptr; + delete _ref_count; + } + + this->_ptr = other._ptr; + _ref_count = other._ref_count; + ++*_ref_count; + } + return *this; + } + + /** + * Fetch our reference count pointer. + */ + unsigned * reference_count_pointer() const + { + return _ref_count; + } + }; + + /** + * Reference counted pointer class (specialisation for InternalCountTag). + * + * \ingroup Pointer + */ + template <typename T_, typename DereferencePolicy_> + class CountedPtr<T_, count_policy::InternalCountTag, DereferencePolicy_> : + public counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_> + { + public: + /** + * Constructor, from a raw pointer. + */ + explicit CountedPtr(T_ * const ptr) : + counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_>(ptr) + { + if (0 != this->_ptr) + ++*this->_ptr->reference_count_pointer(); + } + + /** + * Constructor, from another CountedPtr. + */ + CountedPtr(const CountedPtr & other) : + counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_>(other._ptr) + { + if (0 != this->_ptr) + ++*this->_ptr->reference_count_pointer(); + } + + /** + * Constructor, from another CountedPtr of a descendent of our + * data's class. + */ + template <typename O_> + CountedPtr(const CountedPtr<O_, count_policy::InternalCountTag> & other) : + counted_ptr_internals::CountedPtrBase<T_, DereferencePolicy_>(other.raw_pointer()) + { + if (0 != this->_ptr) + ++*this->_ptr->reference_count_pointer(); + } + + /** + * Destructor. + */ + ~CountedPtr() + { + if (0 != this->_ptr) + if (0 == --(*this->_ptr->reference_count_pointer())) + delete this->_ptr; + } + + /** + * Assignment, from another CountedPtr. + */ + const CountedPtr & operator= (const CountedPtr & other) + { + if (other._ptr != this->_ptr) + { + if (0 != this->_ptr) + if (0 == --(*this->_ptr->reference_count_pointer())) + delete this->_ptr; + + this->_ptr = other._ptr; + if (0 != this->_ptr) + ++*this->_ptr->reference_count_pointer(); + } + return *this; + } + + /** + * Fetch our reference count pointer. + */ + unsigned * reference_count_pointer() const + { + if (0 != this->_ptr) + return this->_ptr->reference_count_pointer(); + else + return 0; + } + }; +} + +#include <paludis/instantiation_policy.hh> + +namespace paludis +{ + /** + * Base class for an internally counted class. + * + * \ingroup Pointer + */ + template <typename T_, typename DereferencePolicy_> + class InternalCounted : + private InstantiationPolicy<InternalCounted<T_, DereferencePolicy_>, + instantiation_method::NonCopyableTag> + { + private: + mutable unsigned _ref_count; + + protected: + /** + * Constructor. + */ + InternalCounted() : + _ref_count(0) + { + } + + /** + * Destructor. + */ + ~InternalCounted() + { + } + + public: + /** + * A CountedPtr to us. + */ + typedef CountedPtr<T_, count_policy::InternalCountTag, DereferencePolicy_> Pointer; + + /** + * A CountedPtr to us (const). + */ + typedef CountedPtr<const T_, count_policy::InternalCountTag, DereferencePolicy_> ConstPointer; + + /** + * Fetch a pointer to our reference count (may be zero). + */ + unsigned * reference_count_pointer() const + { + return & _ref_count; + } + }; +} + +#endif + diff --git a/paludis/counted_ptr_TEST.cc b/paludis/counted_ptr_TEST.cc new file mode 100644 index 000000000..aec802089 --- /dev/null +++ b/paludis/counted_ptr_TEST.cc @@ -0,0 +1,350 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "counted_ptr.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <string> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for counted_ptr.hh . + * + * \ingroup Test + * \ingroup Pointer + */ + +#ifndef DOXYGEN +class MyClass : public InternalCounted<MyClass> +{ + private: + int _v; + + public: + MyClass(const int v) : + _v(v) + { + } + + MyClass(const MyClass & other) : + InternalCounted<MyClass>(), + _v(other._v) + { + } + + const MyClass & operator= (const MyClass & other) + { + _v = other._v; + return *this; + } + + bool operator== (const MyClass & other) const + { + return _v == other._v; + } + + int value() const + { + return _v; + } +}; + +std::ostream & operator<< (std::ostream & s, const MyClass & c) +{ + s << c.value(); + return s; +} +#endif + +namespace test_cases +{ + /** + * \test CountedPtr creation tests. + * + * \ingroup Test + */ + struct CountedPtrCreationTests : TestCase + { + CountedPtrCreationTests() : TestCase("CountedPtr creation tests") { } + + void run() + { + CountedPtr<int, count_policy::ExternalCountTag> i(new int(10)); + CountedPtr<std::string, count_policy::ExternalCountTag> j(new std::string("moo")); + } + } test_counted_ptr_creation; + + /** + * \test CountedPtr dereference tests. + * + * \ingroup Test + */ + struct CountedPtrDereferenceTests : TestCase + { + CountedPtrDereferenceTests() : TestCase("CountedPtr dereference tests") { } + + void run() + { + CountedPtr<int, count_policy::ExternalCountTag> i(new int(10)); + TEST_CHECK_EQUAL(*i, 10); + + CountedPtr<std::string, count_policy::ExternalCountTag> j(new std::string("moo")); + TEST_CHECK_EQUAL(*j, "moo"); + TEST_CHECK_EQUAL(j->length(), 3); + } + } counted_ptr_dereference_tests; + + /** + * \test CountedPtr copy tests. + * + * \ingroup Test + */ + struct CountedPtrCopyTests : TestCase + { + CountedPtrCopyTests() : TestCase("CountedPtr copy tests") { } + + void run() + { + CountedPtr<int, count_policy::ExternalCountTag> i(new int(10)); + TEST_CHECK_EQUAL(*i, 10); + + CountedPtr<int, count_policy::ExternalCountTag> i2(i); + TEST_CHECK_EQUAL(*i, 10); + TEST_CHECK_EQUAL(*i2, 10); + } + } counted_ptr_copy_tests; + + /** + * \test CountedPtr dereference-assign tests. + * + * \ingroup Test + */ + struct CountedPtrDereferenceAssignTests : TestCase + { + CountedPtrDereferenceAssignTests() : TestCase("CountedPtr dereference assign tests") { } + + void run() + { + CountedPtr<int, count_policy::ExternalCountTag> i(new int(10)); + TEST_CHECK_EQUAL(*i, 10); + *i = 20; + TEST_CHECK_EQUAL(*i, 20); + + CountedPtr<int, count_policy::ExternalCountTag> i2(i); + TEST_CHECK_EQUAL(*i, 20); + TEST_CHECK_EQUAL(*i2, 20); + + *i = 30; + TEST_CHECK_EQUAL(*i, 30); + TEST_CHECK_EQUAL(*i2, 30); + + *i2 = 40; + TEST_CHECK_EQUAL(*i, 40); + TEST_CHECK_EQUAL(*i2, 40); + } + } counted_ptr_dereference_assign_tests; + + /** + * \test CountedPtr assign value tests. + * + * \ingroup Test + */ + struct CountedPtrAssignValueTests : TestCase + { + CountedPtrAssignValueTests() : TestCase("CountedPtr assign value tests") { } + + void run() + { + CountedPtr<int, count_policy::ExternalCountTag> i(new int(10)); + TEST_CHECK_EQUAL(*i, 10); + CountedPtr<int, count_policy::ExternalCountTag> i2(i); + TEST_CHECK_EQUAL(*i, 10); + TEST_CHECK_EQUAL(*i2, 10); + + i = CountedPtr<int, count_policy::ExternalCountTag>(new int(20)); + TEST_CHECK_EQUAL(*i, 20); + TEST_CHECK_EQUAL(*i2, 10); + } + } counted_ptr_assign_value_tests; + + /** + * \test CountedPtr assign pointer tests. + * + * \ingroup Test + */ + struct CountedPtrAssignPointerTests : TestCase + { + CountedPtrAssignPointerTests() : TestCase("CountedPtr assign pointer tests") { } + + void run() + { + CountedPtr<int, count_policy::ExternalCountTag> i(new int(10)); + TEST_CHECK_EQUAL(*i, 10); + CountedPtr<int, count_policy::ExternalCountTag> i2(i); + TEST_CHECK_EQUAL(*i, 10); + TEST_CHECK_EQUAL(*i2, 10); + + CountedPtr<int, count_policy::ExternalCountTag> i3(new int(30)); + + i = i3; + TEST_CHECK_EQUAL(*i, 30); + TEST_CHECK_EQUAL(*i2, 10); + TEST_CHECK_EQUAL(*i3, 30); + } + } counted_ptr_assign_pointer_tests; + + /** + * \test CountedPtr internal creation tests. + * + * \ingroup Test + */ + struct CountedPtrInternalCreationTests : TestCase + { + CountedPtrInternalCreationTests() : TestCase("CountedPtr internal creation tests") { } + + void run() + { + MyClass::Pointer i(new MyClass(10)); + } + } test_counted_ptr_internal_creation; + + /** + * \test CountedPtr internal dereference tests. + * + * \ingroup Test + */ + struct CountedPtrInternalDereferenceTests : TestCase + { + CountedPtrInternalDereferenceTests() : TestCase("CountedPtr internal dereference tests") { } + + void run() + { + MyClass::Pointer i(new MyClass(10)); + TEST_CHECK_EQUAL(*i, 10); + + MyClass::Pointer j(new MyClass(20)); + TEST_CHECK_EQUAL(*j, 20); + } + } counted_ptr_internal_dereference_tests; + + /** + * \test CountedPtr internal copy tests. + * + * \ingroup Test + */ + struct CountedPtrInternalCopyTests : TestCase + { + CountedPtrInternalCopyTests() : TestCase("CountedPtr internal copy tests") { } + + void run() + { + MyClass::Pointer i(new MyClass(10)); + TEST_CHECK_EQUAL(*i, 10); + + MyClass::Pointer i2(i); + TEST_CHECK_EQUAL(*i, 10); + TEST_CHECK_EQUAL(*i2, 10); + } + } counted_ptr_internal_copy_tests; + + /** + * \test CountedPtr internal dereference-assign tests. + * + * \ingroup Test + */ + struct CountedPtrInternalDereferenceAssignTests : TestCase + { + CountedPtrInternalDereferenceAssignTests() : + TestCase("CountedPtr internal dereference assign tests") { } + + void run() + { + MyClass::Pointer i(new MyClass(10)); + TEST_CHECK_EQUAL(*i, 10); + *i = 20; + TEST_CHECK_EQUAL(*i, 20); + + MyClass::Pointer i2(i); + TEST_CHECK_EQUAL(*i, 20); + TEST_CHECK_EQUAL(*i2, 20); + + *i = 30; + TEST_CHECK_EQUAL(*i, 30); + TEST_CHECK_EQUAL(*i2, 30); + + *i2 = 40; + TEST_CHECK_EQUAL(*i, 40); + TEST_CHECK_EQUAL(*i2, 40); + } + } counted_ptr_internal_dereference_assign_tests; + + /** + * \test CountedPtr internal assign value tests. + * + * \ingroup Test + */ + struct CountedPtrInternalAssignValueTests : TestCase + { + CountedPtrInternalAssignValueTests() : + TestCase("CountedPtr internal assign value tests") { } + + void run() + { + MyClass::Pointer i(new MyClass(10)); + TEST_CHECK_EQUAL(*i, 10); + MyClass::Pointer i2(i); + TEST_CHECK_EQUAL(*i, 10); + TEST_CHECK_EQUAL(*i2, 10); + + i = MyClass::Pointer(new MyClass(20)); + TEST_CHECK_EQUAL(*i, 20); + TEST_CHECK_EQUAL(*i2, 10); + } + } counted_ptr_internal_assign_value_tests; + + /** + * \test CountedPtr internal assign pointer tests. + * + * \ingroup Test + */ + struct CountedPtrInternalAssignPointerTests : TestCase + { + CountedPtrInternalAssignPointerTests() : + TestCase("CountedPtr internal assign pointer tests") { } + + void run() + { + MyClass::Pointer i(new MyClass(10)); + TEST_CHECK_EQUAL(*i, 10); + MyClass::Pointer i2(i); + TEST_CHECK_EQUAL(*i, 10); + TEST_CHECK_EQUAL(*i2, 10); + + MyClass::Pointer i3(new MyClass(30)); + + i = i3; + TEST_CHECK_EQUAL(*i, 30); + TEST_CHECK_EQUAL(*i2, 10); + TEST_CHECK_EQUAL(*i3, 30); + } + } counted_ptr_internal_assign_pointer_tests; +} + diff --git a/paludis/counted_ptr_error.cc b/paludis/counted_ptr_error.cc new file mode 100644 index 000000000..e72937062 --- /dev/null +++ b/paludis/counted_ptr_error.cc @@ -0,0 +1,29 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "counted_ptr_error.hh" + +using namespace paludis; + +CountedPtrError::CountedPtrError() throw () : + Exception("CountedPtr dereference error") +{ +} + diff --git a/paludis/counted_ptr_error.hh b/paludis/counted_ptr_error.hh new file mode 100644 index 000000000..f3a39c80c --- /dev/null +++ b/paludis/counted_ptr_error.hh @@ -0,0 +1,51 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_COUNTED_PTR_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_COUNTED_PTR_ERROR_HH 1 + +#include <paludis/exception.hh> + +/** \file + * Declarations for the CountedPtrError exception class. + * + * \ingroup Pointer + * \ingroup Exception + */ + +namespace paludis +{ + /** + * Thrown when a CountedPtr check fails. + * + * \ingroup Pointer + * \ingroup Exception + */ + class CountedPtrError : public Exception + { + public: + /** + * Constructor. + */ + CountedPtrError() throw (); + }; +} + +#endif diff --git a/paludis/create_insert_iterator.cc b/paludis/create_insert_iterator.cc new file mode 100644 index 000000000..b8585d763 --- /dev/null +++ b/paludis/create_insert_iterator.cc @@ -0,0 +1,4 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "create_insert_iterator.hh" + diff --git a/paludis/create_insert_iterator.hh b/paludis/create_insert_iterator.hh new file mode 100644 index 000000000..2a3341c86 --- /dev/null +++ b/paludis/create_insert_iterator.hh @@ -0,0 +1,111 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_CREATE_INSERT_ITERATOR_HH +#define PALUDIS_GUARD_PALUDIS_CREATE_INSERT_ITERATOR_HH 1 + +#include <functional> +#include <iterator> + +namespace paludis +{ + template <typename Iter_, typename Type_> + class CreateInsertIterator : + public std::iterator<typename std::iterator_traits<Iter_>::iterator_category, void, void, void, void> + { + private: + Iter_ _i; + + public: + struct container_type + { + typedef Type_ value_type; + }; + + /** + * Constructor, from an iterator. + */ + CreateInsertIterator(const Iter_ & i) : + _i(i) + { + } + + /** + * Copy constructor. + */ + CreateInsertIterator(const CreateInsertIterator & other) : + _i(other._i) + { + } + + /** + * Assignment. + */ + template <typename T_> + const CreateInsertIterator & operator= (const T_ value) + { + *_i = Type_(value); + return *this; + } + + /** + * Dereference. + */ + CreateInsertIterator & operator* () + { + return *this; + } + + /** + * Dereference arrow. + */ + CreateInsertIterator * operator-> () + { + return this; + } + + /** + * Increment. + */ + CreateInsertIterator & operator++ () + { + return *this; + } + + /** + * Increment. + */ + CreateInsertIterator & operator++ (int) + { + return *this; + } + }; + + /** + * Convenience function: make a TranslateInsertIterator. + */ + template <typename Type_, typename Iter_> + CreateInsertIterator<Iter_, Type_> create_inserter(const Iter_ & i) + { + return CreateInsertIterator<Iter_, Type_>(i); + } +} + +#endif diff --git a/paludis/create_insert_iterator_TEST.cc b/paludis/create_insert_iterator_TEST.cc new file mode 100644 index 000000000..b83559055 --- /dev/null +++ b/paludis/create_insert_iterator_TEST.cc @@ -0,0 +1,45 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "create_insert_iterator.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <vector> +#include <algorithm> + +using namespace paludis; +using namespace test; + +#ifndef DOXYGEN +struct C +{ + std::string s; + + explicit C(const std::string & ss) : + s(ss) + { + } +}; +#endif + +namespace test_cases +{ + struct CreateInsertIteratorTest : TestCase + { + CreateInsertIteratorTest() : TestCase("create insert iterator") { } + + void run() + { + std::vector<std::string> v; + v.push_back("one"); + v.push_back("two"); + + std::vector<C> vv; + std::copy(v.begin(), v.end(), create_inserter<C>(std::back_inserter(vv))); + + TEST_CHECK_EQUAL(vv.size(), 2); + TEST_CHECK_EQUAL(vv.at(0).s, "one"); + TEST_CHECK_EQUAL(vv.at(1).s, "two"); + } + } test_create_insert_iterator; +} + diff --git a/paludis/default_config.cc b/paludis/default_config.cc new file mode 100644 index 000000000..6848505b7 --- /dev/null +++ b/paludis/default_config.cc @@ -0,0 +1,199 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "default_config.hh" +#include "fs_entry.hh" +#include "dir_iterator.hh" +#include "getenv.hh" +#include "key_value_config_file.hh" +#include "default_config_error.hh" +#include "filter_insert_iterator.hh" +#include "is_file_with_extension.hh" +#include "stringify.hh" +#include "tokeniser.hh" +#include "line_config_file.hh" +#include "create_insert_iterator.hh" +#include <fstream> +#include <algorithm> + +using namespace paludis; + +DefaultConfig::DefaultConfig() +{ + Context context("When loading default configuration:"); + + Tokeniser<delim_kind::AnyOfTag, delim_mode::DelimiterTag> tokeniser(" \t\n"); + + /* repositories */ + { + std::list<FSEntry> dirs; + if (! getenv_with_default("PALUDIS_CONFIG_DIR", "").empty()) + dirs.push_back(FSEntry(getenv_or_error("PALUDIS_CONFIG_DIR")) / "repositories"); + else + { + dirs.push_back(FSEntry(getenv_with_default("ROOT", "/") + "" SYSCONFDIR) + / "paludis" / "repositories"); + dirs.push_back(FSEntry(getenv_or_error("HOME")) / ".paludis" / "repositories"); + } + + std::list<FSEntry> repo_files; + for (std::list<FSEntry>::const_iterator dir(dirs.begin()), dir_end(dirs.end()) ; + dir != dir_end ; ++dir) + { + if (! dir->exists()) + continue; + + std::copy(DirIterator(*dir), DirIterator(), + filter_inserter(std::back_inserter(repo_files), IsFileWithExtension(".conf"))); + } + + for (std::list<FSEntry>::const_iterator repo_file(repo_files.begin()), repo_file_end(repo_files.end()) ; + repo_file != repo_file_end ; ++repo_file) + { + Context local_context("When reading repository file '" + stringify(*repo_file) + "':"); + + std::ifstream kf(stringify(*repo_file).c_str()); + if (! kf) + throw DefaultConfigError("Couldn't open " + stringify(*repo_file)); + + KeyValueConfigFile k(&kf); + + if (k.get("location").empty()) + throw DefaultConfigError("Key 'location' empty or not specified in " + + stringify(*repo_file)); + if (k.get("format").empty()) + throw DefaultConfigError("Key 'format' empty or not specified in " + + stringify(*repo_file)); + if (k.get("profile").empty()) + throw DefaultConfigError("Key 'profile' empty or not specified in " + + stringify(*repo_file)); + + _repos.push_back(RepositoryConfigEntry(k.get("location"), + k.get("profile"), k.get("format"))); + } + + if (_repos.empty()) + throw DefaultConfigError("No repositories specified"); + } + + /* keywords */ + { + std::list<FSEntry> files; + if (! getenv_with_default("PALUDIS_CONFIG_DIR", "").empty()) + files.push_back(FSEntry(getenv_or_error("PALUDIS_CONFIG_DIR")) / "keywords.conf"); + else + { + files.push_back(FSEntry(getenv_with_default("ROOT", "/") + "" SYSCONFDIR) + / "paludis" / "keywords.conf"); + files.push_back(FSEntry(getenv_or_error("HOME")) / ".paludis" / "keywords.conf"); + } + + for (std::list<FSEntry>::const_iterator file(files.begin()), file_end(files.end()) ; + file != file_end ; ++file) + { + Context local_context("When reading keywords file '" + stringify(*file) + "':"); + + if (! file->is_regular_file()) + continue; + + std::ifstream kf(stringify(*file).c_str()); + if (! kf) + throw DefaultConfigError("Couldn't open " + stringify(*file)); + + LineConfigFile f(&kf); + for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ; + line != line_end ; ++line) + { + std::vector<std::string> tokens; + tokeniser.tokenise(*line, std::back_inserter(tokens)); + if (tokens.empty()) + continue; + if ("*" == tokens.at(0)) + { + _default_keywords.clear(); + std::copy(++(tokens.begin()), tokens.end(), + create_inserter<KeywordName>(std::back_inserter(_default_keywords))); + } + else + { + PackageDepAtom::ConstPointer a(new PackageDepAtom(tokens.at(0))); + for (std::vector<std::string>::const_iterator t(++(tokens.begin())), t_end(tokens.end()) ; + t != t_end ; ++t) + _keywords[a->package()].push_back(std::make_pair(a, *t)); + } + } + } + + if (_default_keywords.empty()) + throw DefaultConfigError("No default keywords specified (a keywords.conf file should " + "contain an entry in the form '* keyword')"); + } + + /* user mask */ + { + std::list<FSEntry> files; + if (! getenv_with_default("PALUDIS_CONFIG_DIR", "").empty()) + files.push_back(FSEntry(getenv_or_error("PALUDIS_CONFIG_DIR")) / "package_mask.conf"); + else + { + files.push_back(FSEntry(getenv_with_default("ROOT", "/") + "" SYSCONFDIR) + / "paludis" / "package_mask.conf"); + files.push_back(FSEntry(getenv_or_error("HOME")) / ".paludis" / "package_mask.conf"); + } + + for (std::list<FSEntry>::const_iterator file(files.begin()), file_end(files.end()) ; + file != file_end ; ++file) + { + Context local_context("When reading package_mask file '" + stringify(*file) + "':"); + + if (! file->is_regular_file()) + continue; + + std::ifstream kf(stringify(*file).c_str()); + if (! kf) + throw DefaultConfigError("Couldn't open " + stringify(*file)); + + LineConfigFile f(&kf); + for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ; + line != line_end ; ++line) + { + PackageDepAtom::ConstPointer a(new PackageDepAtom(*line)); + _user_masks[a->package()].push_back(a); + } + } + } + + /* user unmask */ + { + std::list<FSEntry> files; + if (! getenv_with_default("PALUDIS_CONFIG_DIR", "").empty()) + files.push_back(FSEntry(getenv_or_error("PALUDIS_CONFIG_DIR")) / "package_unmask.conf"); + else + { + files.push_back(FSEntry(getenv_with_default("ROOT", "/") + "" SYSCONFDIR) + / "paludis" / "package_unmask.conf"); + files.push_back(FSEntry(getenv_or_error("HOME")) / ".paludis" / "package_unmask.conf"); + } + + for (std::list<FSEntry>::const_iterator file(files.begin()), file_end(files.end()) ; + file != file_end ; ++file) + { + Context local_context("When reading package_unmask file '" + stringify(*file) + "':"); + + if (! file->is_regular_file()) + continue; + + std::ifstream kf(stringify(*file).c_str()); + if (! kf) + throw DefaultConfigError("Couldn't open " + stringify(*file)); + + LineConfigFile f(&kf); + for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ; + line != line_end ; ++line) + { + PackageDepAtom::ConstPointer a(new PackageDepAtom(*line)); + _user_unmasks[a->package()].push_back(a); + } + } + } +} + diff --git a/paludis/default_config.hh b/paludis/default_config.hh new file mode 100644 index 000000000..f8c54f642 --- /dev/null +++ b/paludis/default_config.hh @@ -0,0 +1,169 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_DEFAULT_CONFIG_HH +#define PALUDIS_GUARD_PALUDIS_DEFAULT_CONFIG_HH 1 + +#include <paludis/instantiation_policy.hh> +#include <paludis/smart_record.hh> +#include <paludis/fs_entry.hh> +#include <paludis/qualified_package_name.hh> +#include <paludis/package_dep_atom.hh> +#include <paludis/keyword_name.hh> +#include <paludis/indirect_iterator.hh> +#include <map> +#include <vector> + +namespace paludis +{ + enum RepositoryConfigEntryKeys + { + rce_location, + rce_profile, + rce_format + }; + + struct RepositoryConfigEntryTag : + SmartRecordTag<comparison_mode::FullComparisonTag, comparison_method::SmartRecordCompareByAllTag>, + SmartRecordKeys<RepositoryConfigEntryKeys, 3>, + SmartRecordKey<rce_location, FSEntry>, + SmartRecordKey<rce_profile, FSEntry>, + SmartRecordKey<rce_format, std::string> + { + }; + + typedef MakeSmartRecord<RepositoryConfigEntryTag>::Type RepositoryConfigEntry; + + class DefaultConfig : + public InstantiationPolicy<DefaultConfig, instantiation_method::SingletonAsNeededTag> + { + friend class InstantiationPolicy<DefaultConfig, instantiation_method::SingletonAsNeededTag>; + + private: + DefaultConfig(); + + std::list<RepositoryConfigEntry> _repos; + + std::map<QualifiedPackageName, std::vector< + std::pair<PackageDepAtom::ConstPointer, KeywordName> > > _keywords; + + const std::vector<std::pair<PackageDepAtom::ConstPointer, KeywordName> > _empty_keywords; + + std::vector<KeywordName> _default_keywords; + + std::map<QualifiedPackageName, std::vector<PackageDepAtom::ConstPointer> > _user_masks; + + std::map<QualifiedPackageName, std::vector<PackageDepAtom::ConstPointer> > _user_unmasks; + + std::vector<PackageDepAtom::ConstPointer> _empty_masks; + + public: + typedef std::list<RepositoryConfigEntry>::const_iterator RepositoryIterator; + + RepositoryIterator begin_repositories() const + { + return _repos.begin(); + } + + RepositoryIterator end_repositories() const + { + return _repos.end(); + } + + typedef std::vector<std::pair<PackageDepAtom::ConstPointer, KeywordName> >::const_iterator + PackageKeywordsIterator; + + PackageKeywordsIterator begin_package_keywords(const QualifiedPackageName & d) const + { + std::map<QualifiedPackageName, std::vector< + std::pair<PackageDepAtom::ConstPointer, KeywordName> > >::const_iterator r; + if (_keywords.end() != ((r = _keywords.find(d)))) + return r->second.begin(); + else + return _empty_keywords.begin(); + } + + PackageKeywordsIterator end_package_keywords(const QualifiedPackageName & d) const + { + std::map<QualifiedPackageName, std::vector< + std::pair<PackageDepAtom::ConstPointer, KeywordName> > >::const_iterator r; + if (_keywords.end() != ((r = _keywords.find(d)))) + return r->second.end(); + else + return _empty_keywords.end(); + } + + typedef std::vector<KeywordName>::const_iterator DefaultKeywordsIterator; + + DefaultKeywordsIterator begin_default_keywords() const + { + return _default_keywords.begin(); + } + + DefaultKeywordsIterator end_default_keywords() const + { + return _default_keywords.end(); + } + + typedef IndirectIterator<std::vector<PackageDepAtom::ConstPointer>::const_iterator, + const PackageDepAtom> UserMasksIterator; + + UserMasksIterator begin_user_masks(const QualifiedPackageName & d) const + { + std::map<QualifiedPackageName, std::vector<PackageDepAtom::ConstPointer> >::const_iterator r; + if (_user_masks.end() != ((r = _user_masks.find(d)))) + return r->second.begin(); + else + return _empty_masks.begin(); + } + + UserMasksIterator end_user_masks(const QualifiedPackageName & d) const + { + std::map<QualifiedPackageName, std::vector<PackageDepAtom::ConstPointer> >::const_iterator r; + if (_user_masks.end() != ((r = _user_masks.find(d)))) + return r->second.end(); + else + return _empty_masks.end(); + } + + typedef IndirectIterator<std::vector<PackageDepAtom::ConstPointer>::const_iterator, + const PackageDepAtom> UserUnmasksIterator; + + UserUnmasksIterator begin_user_unmasks(const QualifiedPackageName & d) const + { + std::map<QualifiedPackageName, std::vector<PackageDepAtom::ConstPointer> >::const_iterator r; + if (_user_unmasks.end() != ((r = _user_unmasks.find(d)))) + return r->second.begin(); + else + return _empty_masks.begin(); + } + + UserUnmasksIterator end_user_unmasks(const QualifiedPackageName & d) const + { + std::map<QualifiedPackageName, std::vector<PackageDepAtom::ConstPointer> >::const_iterator r; + if (_user_unmasks.end() != ((r = _user_unmasks.find(d)))) + return r->second.end(); + else + return _empty_masks.end(); + } + }; +} + +#endif diff --git a/paludis/default_config_error.cc b/paludis/default_config_error.cc new file mode 100644 index 000000000..53164ce99 --- /dev/null +++ b/paludis/default_config_error.cc @@ -0,0 +1,10 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "default_config_error.hh" + +using namespace paludis; + +DefaultConfigError::DefaultConfigError(const std::string & msg) throw () : + Exception("Default configuration error: " + msg) +{ +} diff --git a/paludis/default_config_error.hh b/paludis/default_config_error.hh new file mode 100644 index 000000000..24b6f1ae7 --- /dev/null +++ b/paludis/default_config_error.hh @@ -0,0 +1,17 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#ifndef PALUDIS_GUARD_PALUDIS_DEFAULT_CONFIG_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEFAULT_CONFIG_ERROR_HH 1 + +#include <paludis/exception.hh> + +namespace paludis +{ + class DefaultConfigError : public Exception + { + public: + DefaultConfigError(const std::string & msg) throw (); + }; +} + +#endif diff --git a/paludis/default_environment.cc b/paludis/default_environment.cc new file mode 100644 index 000000000..29f0bd64f --- /dev/null +++ b/paludis/default_environment.cc @@ -0,0 +1,141 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "default_environment.hh" +#include "default_config_error.hh" +#include "package_database.hh" +#include "portage_repository.hh" +#include "default_config.hh" +#include "stringify.hh" +#include <list> +#include <vector> + +using namespace paludis; + +DefaultEnvironment::DefaultEnvironment() : + Environment(PackageDatabase::Pointer(new PackageDatabase), + PackageDatabase::Pointer(new PackageDatabase)) +{ + Context context("When loading default environment:"); + + for (DefaultConfig::RepositoryIterator r(DefaultConfig::get_instance()->begin_repositories()), + r_end(DefaultConfig::get_instance()->end_repositories()) ; r != r_end ; ++r) + { + /// \todo abstract factory + if (r->get<rce_format>() != "portage") + throw DefaultConfigError("Unknown repository format '" + r->get<rce_format>() + "'"); + Repository::Pointer repo(new PortageRepository(r->get<rce_location>(), + r->get<rce_profile>())); + package_db()->add_repository(repo); + } + + /// \bug vdb +} + +DefaultEnvironment::~DefaultEnvironment() +{ +} + +bool +DefaultEnvironment::query_use(const UseFlagName &, const PackageDatabaseEntry * const) const +{ + /// \todo + return false; +} + +bool +DefaultEnvironment::accept_keyword(const KeywordName & keyword, const PackageDatabaseEntry * const d) const +{ + if (keyword == KeywordName("*")) + return true; + + Context context("When checking accept_keyword of '" + stringify(keyword) + + (d ? "' for " + stringify(*d) : stringify("'")) + ":"); + + bool result(false); + + if (d) + for (DefaultConfig::PackageKeywordsIterator + k(DefaultConfig::get_instance()->begin_package_keywords(d->get<pde_package>())), + k_end(DefaultConfig::get_instance()->end_package_keywords(d->get<pde_package>())) ; + k != k_end ; ++k) + { + if (k->first->package() != d->get<pde_package>()) + continue; + if (k->first->version_spec_ptr() && ! (((d->get<pde_version>()).* + (k->first->version_operator().as_version_spec_operator())) + (*k->first->version_spec_ptr()))) + continue; + /// \bug slot + + result |= k->second == keyword; + } + + result |= DefaultConfig::get_instance()->end_default_keywords() != + std::find(DefaultConfig::get_instance()->begin_default_keywords(), + DefaultConfig::get_instance()->end_default_keywords(), + keyword); + + return result; +} + +bool +DefaultEnvironment::query_user_masks(const PackageDatabaseEntry & d) const +{ + for (DefaultConfig::UserMasksIterator + k(DefaultConfig::get_instance()->begin_user_masks(d.get<pde_package>())), + k_end(DefaultConfig::get_instance()->end_user_masks(d.get<pde_package>())) ; + k != k_end ; ++k) + { + if (k->package() != d.get<pde_package>()) + continue; + if (k->version_spec_ptr() && ! (((d.get<pde_version>()).* + (k->version_operator().as_version_spec_operator())) + (*k->version_spec_ptr()))) + continue; + /// \bug slot + + return true; + } + + return false; +} + +bool +DefaultEnvironment::query_user_unmasks(const PackageDatabaseEntry & d) const +{ + for (DefaultConfig::UserMasksIterator + k(DefaultConfig::get_instance()->begin_user_unmasks(d.get<pde_package>())), + k_end(DefaultConfig::get_instance()->end_user_unmasks(d.get<pde_package>())) ; + k != k_end ; ++k) + { + if (k->package() != d.get<pde_package>()) + continue; + if (k->version_spec_ptr() && ! (((d.get<pde_version>()).* + (k->version_operator().as_version_spec_operator())) + (*k->version_spec_ptr()))) + continue; + /// \bug slot + + return true; + } + + return false; +} + diff --git a/paludis/default_environment.hh b/paludis/default_environment.hh new file mode 100644 index 000000000..9aaea817b --- /dev/null +++ b/paludis/default_environment.hh @@ -0,0 +1,61 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEFAULT_ENVIRONMENT_HH +#define PALUDIS_GUARD_PALUDIS_DEFAULT_ENVIRONMENT_HH 1 + +#include <paludis/environment.hh> +#include <paludis/package_database.hh> + +/** \file + * Declarations for the DefaultEnvironment class. + * + * \ingroup Environment + */ + +namespace paludis +{ + /** + * The DefaultEnvironment is an Environment that corresponds to the normal + * operating evironment. + * + * \ingroup Environment + */ + class DefaultEnvironment : + public Environment, + public InstantiationPolicy<DefaultEnvironment, instantiation_method::SingletonAsNeededTag> + { + friend class InstantiationPolicy<DefaultEnvironment, instantiation_method::SingletonAsNeededTag>; + + private: + DefaultEnvironment(); + + ~DefaultEnvironment(); + + protected: + virtual bool query_use(const UseFlagName &, const PackageDatabaseEntry * const) const; + + virtual bool accept_keyword(const KeywordName &, const PackageDatabaseEntry * const) const; + + virtual bool query_user_masks(const PackageDatabaseEntry &) const; + + virtual bool query_user_unmasks(const PackageDatabaseEntry &) const; + }; +} +#endif diff --git a/paludis/deleter.cc b/paludis/deleter.cc new file mode 100644 index 000000000..9775a35c2 --- /dev/null +++ b/paludis/deleter.cc @@ -0,0 +1,26 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "deleter.hh" + +using namespace paludis; + +Deleter::Deleter() +{ +} diff --git a/paludis/deleter.hh b/paludis/deleter.hh new file mode 100644 index 000000000..21dc4aeb7 --- /dev/null +++ b/paludis/deleter.hh @@ -0,0 +1,55 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DELETER_HH +#define PALUDIS_GUARD_PALUDIS_DELETER_HH 1 + +/** \file + * Declarations for the Deleter class. + * + * \ingroup Utility + */ + +namespace paludis +{ + /** + * A Deleter is a functor that deletes something. + * + * \ingroup Utility + */ + class Deleter + { + public: + /** + * Constructor. + */ + Deleter(); + + /** + * Delete an item. + */ + template <typename T_> + void operator() (T_ t) + { + delete t; + } + }; +} + +#endif diff --git a/paludis/deleter_TEST.cc b/paludis/deleter_TEST.cc new file mode 100644 index 000000000..7ae46457e --- /dev/null +++ b/paludis/deleter_TEST.cc @@ -0,0 +1,79 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "deleter.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <algorithm> +#include <vector> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for deleter.hh. + * + * \ingroup Test + */ + +#ifndef DOXYGEN +struct MyClass +{ + static int instances; + + MyClass() + { + ++instances; + } + + ~MyClass() + { + --instances; + } +}; + +int MyClass::instances = 0; +#endif + +namespace test_cases +{ + /** + * Test Deleter. + * + * \ingroup Test + */ + struct DeleterTest : TestCase + { + DeleterTest() : TestCase("deleter") { } + + void run() + { + std::vector<MyClass *> v; + TEST_CHECK_EQUAL(MyClass::instances, 0); + v.push_back(new MyClass); + TEST_CHECK_EQUAL(MyClass::instances, 1); + v.push_back(new MyClass); + TEST_CHECK_EQUAL(MyClass::instances, 2); + v.push_back(new MyClass); + TEST_CHECK_EQUAL(MyClass::instances, 3); + std::for_each(v.begin(), v.end(), Deleter()); + TEST_CHECK_EQUAL(MyClass::instances, 0); + } + } test_deleter; +} diff --git a/paludis/dep_atom.cc b/paludis/dep_atom.cc new file mode 100644 index 000000000..58f0df9aa --- /dev/null +++ b/paludis/dep_atom.cc @@ -0,0 +1,31 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_atom.hh" + +using namespace paludis; + +DepAtom::DepAtom() +{ +} + +DepAtom::~DepAtom() +{ +} + diff --git a/paludis/dep_atom.hh b/paludis/dep_atom.hh new file mode 100644 index 000000000..3100851d3 --- /dev/null +++ b/paludis/dep_atom.hh @@ -0,0 +1,58 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_ATOM_HH +#define PALUDIS_GUARD_PALUDIS_DEP_ATOM_HH 1 + +#include <paludis/visitor_pattern.hh> +#include <paludis/composite_pattern.hh> +#include <paludis/instantiation_policy.hh> +#include <paludis/counted_ptr.hh> + +/** \file + * Declarations for the DepAtom class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + class DepAtomVisitor; + class CompositeDepAtom; + + /** + * Base class for a dependency atom. + * + * \ingroup DepResolver + */ + class DepAtom : + public virtual VisitableInterface<DepAtomVisitor>, + public virtual Composite<DepAtom, CompositeDepAtom>, + private InstantiationPolicy<DepAtom, instantiation_method::NonCopyableTag>, + public InternalCounted<DepAtom> + { + protected: + DepAtom(); + + public: + virtual ~DepAtom(); + }; +} + +#endif diff --git a/paludis/dep_atom_dumper.cc b/paludis/dep_atom_dumper.cc new file mode 100644 index 000000000..dd81d8244 --- /dev/null +++ b/paludis/dep_atom_dumper.cc @@ -0,0 +1,93 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "block_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include "dep_atom_dumper.hh" + +#include "visitor_pattern-impl.hh" +#include "composite_visitor_pattern-impl.hh" + +using namespace paludis; + +DepAtomDumper::DepAtomDumper(std::ostream * const o) : + _o(o) +{ +} + +void +DepAtomDumper::enter(const AllDepAtom * const) +{ + *_o << "<all>"; +} + +void +DepAtomDumper::leave(const AllDepAtom * const) +{ + *_o << "</all>"; +} + +void +DepAtomDumper::enter(const AnyDepAtom * const) +{ + *_o << "<any>"; +} + +void +DepAtomDumper::leave(const AnyDepAtom * const) +{ + *_o << "</any>"; +} + +void +DepAtomDumper::enter(const UseDepAtom * const f) +{ + *_o << "<use flag=\"" << f->flag() << "\" inverse=\"" + << (f->inverse() ? "true" : "false") << "\">"; +} + +void +DepAtomDumper::leave(const UseDepAtom * const) +{ + *_o << "</use>"; +} + +void +DepAtomDumper::visit(const PackageDepAtom * const p) +{ + *_o << "<package"; + if (p->slot_ptr()) + *_o << " slot=\"" << *p->slot_ptr() << "\""; + if (p->version_spec_ptr()) + *_o << " version=\"" << p->version_operator() << *p->version_spec_ptr() << "\""; + *_o << ">" << p->package() << "</package>"; +} + +void +DepAtomDumper::visit(const BlockDepAtom * const b) +{ + *_o << "<block>"; + b->blocked_atom()->accept(this); + *_o << "</block>"; +} + diff --git a/paludis/dep_atom_dumper.hh b/paludis/dep_atom_dumper.hh new file mode 100644 index 000000000..e8f9b3a3c --- /dev/null +++ b/paludis/dep_atom_dumper.hh @@ -0,0 +1,66 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_ATOM_DUMPER_HH +#define PALUDIS_GUARD_PALUDIS_DEP_ATOM_DUMPER_HH 1 + +#include <paludis/dep_atom_visitor.hh> +#include <paludis/instantiation_policy.hh> +#include <ostream> + +/** \file + * Declarations for the DepAtomDumper class. + */ + +namespace paludis +{ + /** + * Dump dependency atoms to a stream in pseudo-XML form, for testing. + */ + class DepAtomDumper : public DepAtomVisitor, + public VisitsComposite<DepAtomDumper, AllDepAtom>, + public VisitsComposite<DepAtomDumper, AnyDepAtom>, + public VisitsComposite<DepAtomDumper, UseDepAtom>, + private InstantiationPolicy<DepAtomDumper, instantiation_method::NonCopyableTag> + { + private: + std::ostream * const _o; + + public: + /** + * Constructor. + */ + DepAtomDumper(std::ostream * const o); + + void enter(const AllDepAtom * const); + void leave(const AllDepAtom * const); + + void enter(const AnyDepAtom * const); + void leave(const AnyDepAtom * const); + + void enter(const UseDepAtom * const); + void leave(const UseDepAtom * const); + + void visit(const PackageDepAtom * const); + + void visit(const BlockDepAtom * const); + }; +} + +#endif diff --git a/paludis/dep_atom_dumper_TEST.cc b/paludis/dep_atom_dumper_TEST.cc new file mode 100644 index 000000000..71819c1b3 --- /dev/null +++ b/paludis/dep_atom_dumper_TEST.cc @@ -0,0 +1,68 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 <test/test_framework.hh> +#include <test/test_runner.hh> +#include "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include "dep_atom_dumper.hh" +#include <sstream> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for DepAtomDumper. + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Test DepAtomDumper. + * + * \ingroup Test + */ + struct DepAtomDumperTest : TestCase + { + DepAtomDumperTest() : TestCase("dump") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + AllDepAtom::Pointer all(new AllDepAtom); + PackageDepAtom::Pointer p1(new PackageDepAtom(make_qualified_package_name("one/one"))); + AnyDepAtom::Pointer any(new AnyDepAtom); + PackageDepAtom::Pointer p2(new PackageDepAtom(make_qualified_package_name("two/two"))); + PackageDepAtom::Pointer p3(new PackageDepAtom(make_qualified_package_name("three/three"))); + all->add_child(p1); + all->add_child(any); + any->add_child(p2); + any->add_child(p3); + all->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><package>one/one</package>" + "<any><package>two/two</package><package>three/three</package></any></all>"); + } + } test_dep_atom_dumper; +} diff --git a/paludis/dep_atom_visitor.cc b/paludis/dep_atom_visitor.cc new file mode 100644 index 000000000..404b7959f --- /dev/null +++ b/paludis/dep_atom_visitor.cc @@ -0,0 +1,30 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_atom_visitor.hh" + +using namespace paludis; + +DepAtomVisitor::DepAtomVisitor() +{ +} + +DepAtomVisitor::~DepAtomVisitor() +{ +} diff --git a/paludis/dep_atom_visitor.hh b/paludis/dep_atom_visitor.hh new file mode 100644 index 000000000..d241babd9 --- /dev/null +++ b/paludis/dep_atom_visitor.hh @@ -0,0 +1,65 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_ATOM_VISITOR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_ATOM_VISITOR_HH 1 + +#include <paludis/dep_atom.hh> +#include <paludis/visitor_pattern.hh> +#include <paludis/composite_visitor_pattern.hh> + +/** \file + * Declarations for the DepAtomVisitor base class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + class PackageDepAtom; + class AllDepAtom; + class AnyDepAtom; + class UseDepAtom; + class BlockDepAtom; + + /** + * A DepAtomVisitor is a generic base class for traversing a DepAtom + * collection. + */ + class DepAtomVisitor : public virtual Visits<PackageDepAtom>, + public virtual Visits<AllDepAtom>, + public virtual Visits<AnyDepAtom>, + public virtual Visits<UseDepAtom>, + public virtual Visits<BlockDepAtom> + { + protected: + /** + * Constructor. + */ + DepAtomVisitor(); + + public: + /** + * Destructor. + */ + virtual ~DepAtomVisitor(); + }; +} + +#endif diff --git a/paludis/dep_lexer.cc b/paludis/dep_lexer.cc new file mode 100644 index 000000000..b4da33305 --- /dev/null +++ b/paludis/dep_lexer.cc @@ -0,0 +1,66 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include "dep_lexer.hh" +#include "exception.hh" +#include "dep_string_lex_error.hh" +#include "tokeniser.hh" +#include <vector> + +using namespace paludis; + +DepLexer::DepLexer(const std::string & s) +{ + Context context("When lexing dependency string '" + s + "':"); + + Tokeniser<delim_kind::AnyOfTag, delim_mode::BoundaryTag> tokeniser(" \n\t"); + std::vector<std::string> tokens; + tokeniser.tokenise(s, std::back_inserter(tokens)); + + for (std::vector<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ; + t != t_end ; ++t) + { + if (t->empty()) + continue; + + if (*t == "||") + _tokens.push_back(std::make_pair(dpl_double_bar, *t)); + else if ('|' == (*t)[0]) + throw DepStringLexError(s, "'|' should be followed by '|'"); + else if (*t == "(") + _tokens.push_back(std::make_pair(dpl_open_paren, *t)); + else if ('(' == (*t)[0]) + throw DepStringLexError(s, "'(' should be followed by whitespace"); + else if (*t == ")") + _tokens.push_back(std::make_pair(dpl_close_paren, *t)); + else if (')' == (*t)[0]) + throw DepStringLexError(s, "')' should be followed by whitespace"); + else if (std::string::npos == t->find_first_not_of(" \t\n")) + _tokens.push_back(std::make_pair(dpl_whitespace, *t)); + else if ('?' == (*t)[t->length() - 1]) + _tokens.push_back(std::make_pair(dpl_use_flag, *t)); + else + _tokens.push_back(std::make_pair(dpl_package, *t)); + } +} diff --git a/paludis/dep_lexer.hh b/paludis/dep_lexer.hh new file mode 100644 index 000000000..74eac45b7 --- /dev/null +++ b/paludis/dep_lexer.hh @@ -0,0 +1,86 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_PARSER_LEXER_HH +#define PALUDIS_GUARD_PALUDIS_DEP_PARSER_LEXER_HH 1 + +#include <paludis/instantiation_policy.hh> +#include <list> +#include <string> + +/** \file + * Declarations for the DepLexer class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * Lexemes used by DepLexer. + */ + enum DepLexerLexeme + { + dpl_whitespace, ///< whitespace + dpl_package, ///< a package name + dpl_use_flag, ///< a use flag + dpl_double_bar, ///< a double bar ('any' marker) + dpl_open_paren, ///< open paren + dpl_close_paren ///< close paren + }; + + /** + * Converts a dependency string into a sequence of tokens. + */ + class DepLexer : + private InstantiationPolicy<DepLexer, instantiation_method::NonCopyableTag> + { + private: + std::list<std::pair<DepLexerLexeme, std::string> > _tokens; + + public: + /** + * Iterator for our tokens. + */ + typedef std::list<std::pair<DepLexerLexeme, std::string> >::const_iterator Iterator; + + /** + * Iterator to the start of our tokens. + */ + Iterator begin() const + { + return _tokens.begin(); + } + + /** + * Iterator to the end of our tokens. + */ + Iterator end() const + { + return _tokens.end(); + } + + /** + * Constructor. + */ + DepLexer(const std::string &); + }; +} + +#endif diff --git a/paludis/dep_lexer_TEST.cc b/paludis/dep_lexer_TEST.cc new file mode 100644 index 000000000..71a09a870 --- /dev/null +++ b/paludis/dep_lexer_TEST.cc @@ -0,0 +1,232 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 <test/test_framework.hh> +#include <test/test_runner.hh> +#include "dep_lexer.hh" +#include <sstream> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for DepLexer. + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Test DepLexer with an empty input. + * + * \ingroup Test + */ + struct DepLexerEmptyTest : TestCase + { + DepLexerEmptyTest() : TestCase("empty") { } + + void run() + { + DepLexer l(""); + DepLexer::Iterator i(l.begin()); + TEST_CHECK(i == l.end()); + } + } test_dep_atom_parser_lexer_empty; + + /** + * \test Test DepLexer with a blank input. + * + * \ingroup Test + */ + struct DepLexerBlankTest : TestCase + { + DepLexerBlankTest() : TestCase("blank") { } + + void run() + { + DepLexer l(" \n \t"); + DepLexer::Iterator i(l.begin()); + TEST_CHECK(i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " \n \t"); + TEST_CHECK(++i == l.end()); + } + } test_dep_atom_parser_lexer_blank; + + /** + * \test Test DepLexer with a package. + * + * \ingroup Test + */ + struct DepLexerPackageTest : TestCase + { + DepLexerPackageTest() : TestCase("package") { } + + void run() + { + DepLexer l("app-editors/vim"); + DepLexer::Iterator i(l.begin()); + TEST_CHECK(i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "app-editors/vim"); + TEST_CHECK(++i == l.end()); + } + } test_dep_atom_parser_lexer_package; + + /** + * \test Test DepParser with a sequence of packages. + * + * \ingroup Test + */ + struct DepLexerPackagesTest : TestCase + { + DepLexerPackagesTest() : TestCase("packages") { } + + void run() + { + DepLexer l("app-editors/vim app-misc/hilite \nsys-apps/findutils"); + DepLexer::Iterator i(l.begin()); + + TEST_CHECK(i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "app-editors/vim"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "app-misc/hilite"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " \n"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "sys-apps/findutils"); + + TEST_CHECK(++i == l.end()); + } + } test_dep_atom_parser_lexer_packages; + + /** + * \test Test DepLexer with an any group. + * + * \ingroup Test + */ + struct DepLexerAnyTest : TestCase + { + DepLexerAnyTest() : TestCase("any") { } + + void run() + { + DepLexer l("|| ( one/one two/two )"); + DepLexer::Iterator i(l.begin()); + + TEST_CHECK(i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_double_bar); + TEST_CHECK_EQUAL(i->second, "||"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_open_paren); + TEST_CHECK_EQUAL(i->second, "("); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "one/one"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "two/two"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_close_paren); + TEST_CHECK_EQUAL(i->second, ")"); + + TEST_CHECK(++i == l.end()); + } + } test_dep_atom_parser_lexer_any; + + /** + * \test Test DepLexer with a use group. + * + * \ingroup Test + */ + struct DepLexerUseTest : TestCase + { + DepLexerUseTest() : TestCase("use") { } + + void run() + { + DepLexer l("foo? ( one/one )"); + DepLexer::Iterator i(l.begin()); + + TEST_CHECK(i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_use_flag); + TEST_CHECK_EQUAL(i->second, "foo?"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_open_paren); + TEST_CHECK_EQUAL(i->second, "("); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_package); + TEST_CHECK_EQUAL(i->second, "one/one"); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_whitespace); + TEST_CHECK_EQUAL(i->second, " "); + + TEST_CHECK(++i != l.end()); + TEST_CHECK_EQUAL(i->first, dpl_close_paren); + TEST_CHECK_EQUAL(i->second, ")"); + + TEST_CHECK(++i == l.end()); + } + } test_dep_atom_parser_lexer_use; +} + + diff --git a/paludis/dep_list.cc b/paludis/dep_list.cc new file mode 100644 index 000000000..808159e22 --- /dev/null +++ b/paludis/dep_list.cc @@ -0,0 +1,479 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_list.hh" +#include "dep_list_error.hh" +#include "dep_list_stack_too_deep_error.hh" +#include "dep_parser.hh" +#include "all_masked_error.hh" +#include "no_resolvable_option_error.hh" +#include "circular_dependency_error.hh" +#include "internal_error.hh" +#include "visitor_pattern-impl.hh" +#include "composite_visitor_pattern-impl.hh" +#include "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "block_dep_atom.hh" +#include "use_dep_atom.hh" +#include "package_dep_atom.hh" +#include "stringify.hh" +#include "container_entry.hh" +#include "save.hh" +#include "indirect_iterator.hh" +#include "block_error.hh" +#include "join.hh" +#include "filter_insert_iterator.hh" + +#include <algorithm> +#include <functional> + +using namespace paludis; + +namespace paludis +{ + template<> + struct Implementation<DepList> : + InstantiationPolicy<Implementation<DepList>, instantiation_method::NonCopyableTag>, + InternalCounted<Implementation<DepList> > + { + const Environment * const environment; + + std::list<DepListEntry> merge_list; + std::list<DepListEntry> pending_list; + bool check_existing_only; + bool in_pdepend; + bool match_found; + const PackageDatabaseEntry * current_package; + int stack_depth; + + bool rdepend_post; + bool drop_circular; + bool drop_self_circular; + bool ignore_installed; + bool recursive_deps; + int max_stack_depth; + + Implementation(const Environment * const e) : + environment(e), + check_existing_only(false), + in_pdepend(false), + match_found(false), + current_package(0), + stack_depth(0), + rdepend_post(false), + drop_circular(false), + drop_self_circular(false), + ignore_installed(false), + recursive_deps(false), + max_stack_depth(100) + { + } + }; +} + +DepList::DepList(const Environment * const e) : + PrivateImplementationPattern<DepList>(new Implementation<DepList>(e)) +{ +} + +DepList::~DepList() +{ +} + +void +DepList::add(DepAtom::ConstPointer atom) +{ + /* keep track of stack depth */ + Save<int> old_stack_depth(&_implementation->stack_depth, + _implementation->stack_depth + 1); + if (_implementation->stack_depth > _implementation->max_stack_depth) + throw DepListStackTooDeepError(_implementation->stack_depth); + + /* we need to make sure that merge_list doesn't get h0rked in the + * event of a failure. */ + bool merge_list_was_empty(_implementation->merge_list.empty()); + std::list<DepListEntry>::iterator m_save(merge_list_was_empty ? + _implementation->merge_list.end() : --(_implementation->merge_list.end())); + + try + { + atom->accept(this); + } + catch (...) + { + if (merge_list_was_empty) + _implementation->merge_list.clear(); + else + _implementation->merge_list.erase(++m_save, _implementation->merge_list.end()); + throw; + } +} + +void +DepList::_add_in_role(DepAtom::ConstPointer atom, const std::string & role) +{ + Context context("When adding " + role + ":"); + add(atom); +} + +DepList::Iterator +DepList::begin() const +{ + return _implementation->merge_list.begin(); +} + +DepList::Iterator +DepList::end() const +{ + return _implementation->merge_list.end(); +} + +void +DepList::enter(const AllDepAtom * const) +{ +} + +void +DepList::leave(const AllDepAtom * const) +{ +} + +struct DepListEntryMatcher : + public std::unary_function<bool, const DepListEntry &> +{ + const PackageDepAtom & atom; + + DepListEntryMatcher(const PackageDepAtom & p) : + atom(p) + { + } + + bool operator() (const DepListEntry & e) const + { + if (e.get<dle_name>() != atom.package()) + return false; + if (atom.slot_ptr()) + if (e.get<dle_slot>() != *atom.slot_ptr()) + return false; + if (atom.version_spec_ptr()) + if (! (((e.get<dle_version>()).*(atom.version_operator().as_version_spec_operator()))( + *atom.version_spec_ptr()))) + return false; + return true; + } +}; + +void +DepList::visit(const PackageDepAtom * const p) +{ + Context context("When resolving package dependency '" + stringify(*p) + "':"); + + bool already_there = false; + bool do_rdepend_post = false; + + /* are we already installed? */ + if ((! _implementation->ignore_installed) && + (! _implementation->environment->installed_db()->query(p)->empty())) + already_there = true; + + /* will we be installed by this point? */ + if ((! already_there) && (_implementation->merge_list.end() != std::find_if( + _implementation->merge_list.begin(), _implementation->merge_list.end(), + DepListEntryMatcher(*p)))) + return; + + if (already_there && ((! _implementation->recursive_deps) || (_implementation->check_existing_only))) + return; + + /* are we allowed to install things? */ + if (_implementation->check_existing_only && ! _implementation->in_pdepend) + { + _implementation->match_found = false; + return; + } + + /* are we pending? (circular dep check) */ + { + std::list<DepListEntry>::iterator i; + if (_implementation->pending_list.end() != ((i = std::find_if( + _implementation->pending_list.begin(), _implementation->pending_list.end(), + DepListEntryMatcher(*p))))) + { + std::list<std::string> entries; + entries.push_front(stringify(*p)); + std::transform(_implementation->pending_list.begin(), ++i, + std::back_inserter(entries), &stringify<DepListEntry>); + if (_implementation->in_pdepend) + return; + else if (_implementation->drop_circular) + return; + else if (_implementation->drop_self_circular && entries.size() <= 2) + return; + else + throw CircularDependencyError(entries.begin(), entries.end()); + } + } + + /* are we allowed to install things? */ + if (_implementation->check_existing_only) + { + _implementation->match_found = false; + return; + } + + /* find the matching package */ + PackageDatabaseEntryCollection::Pointer matches( + _implementation->environment->package_db()->query(p)); + + const PackageDatabaseEntry * match(0); + VersionMetadata::ConstPointer metadata(0); + for (PackageDatabaseEntryCollection::ReverseIterator e(matches->rbegin()), + e_end(matches->rend()) ; e != e_end ; ++e) + { + /* check masks */ + if (_implementation->environment->mask_reasons(*e).any()) + continue; + + metadata = _implementation->environment->package_db()->fetch_metadata(*e); + match = &*e; + break; + } + + if (! match) + throw AllMaskedError(stringify(*p)); + + Save<const PackageDatabaseEntry *> old_current_package(&_implementation->current_package, match); + + context.change_context("When resolving package dependency '" + stringify(*p) + + "' -> '" + stringify(*match) + "':"); + + /* make merge entry */ + DepListEntry merge_entry(match->get<pde_package>(), match->get<pde_version>(), + SlotName(metadata->get(vmk_slot)), match->get<pde_repository>()); + + { + /* pending */ + ContainerEntry<std::list<DepListEntry> > pending(&_implementation->pending_list, merge_entry); + + /* merge dependencies */ + _add_in_role(DepParser::parse(metadata->get(vmk_depend)), "DEPEND"); + + try + { + _add_in_role(DepParser::parse(metadata->get(vmk_rdepend)), "RDEPEND"); + } + catch (const CircularDependencyError &) + { + if (_implementation->rdepend_post) + do_rdepend_post = true; + else + throw; + } + } + + /* merge package */ + if (! already_there) + _implementation->merge_list.push_back(merge_entry); + + /* merge post dependencies */ + { + Save<bool> save_ignore_cdep(&_implementation->in_pdepend, true); + if (do_rdepend_post) + _add_in_role(DepParser::parse(metadata->get(vmk_rdepend)), "RDEPEND (as PDEPEND)"); + _add_in_role(DepParser::parse(metadata->get(vmk_pdepend)), "PDEPEND"); + } +} + +void +DepList::visit(const UseDepAtom * const u) +{ + if (_implementation->environment->query_use(u->flag(), + _implementation->current_package) ^ u->inverse()) + std::for_each(u->begin(), u->end(), std::bind1st(std::mem_fun(&DepList::add), this)); +} + +struct IsViable : + public std::unary_function<bool, DepAtom::ConstPointer> +{ + const Implementation<DepList> & _impl; + + IsViable(const Implementation<DepList> & impl) : + _impl(impl) + { + } + + bool operator() (DepAtom::ConstPointer a) + { + /// \todo don't use dynamic_cast<>, it sucks + const UseDepAtom * u(0); + if (0 != ((u = dynamic_cast<const UseDepAtom *>(a.raw_pointer())))) + return _impl.environment->query_use(u->flag(), + _impl.current_package) ^ u->inverse(); + else + return true; + } +}; + +void +DepList::visit(const AnyDepAtom * const a) +{ + /* try to resolve each of our children in return. note the annoying + * special case for use? () flags: + * + * || ( ) -> nothing + * || ( off1? ( blah1 ) off2? ( blah2 ) blah3 ) -> blah3 + * || ( off1? ( blah1 ) off2? ( blah2 ) ) -> nothing + * || ( ( off1? ( blah1 ) ) blah2 ) -> nothing + * + * we handle this by keeping a list of 'viable children'. + */ + + std::list<DepAtom::ConstPointer> viable_children; + std::copy(a->begin(), a->end(), filter_inserter( + std::back_inserter(viable_children), IsViable(*_implementation))); + + if (viable_children.empty()) + return; + + bool found(false); + for (CompositeDepAtom::Iterator i(viable_children.begin()), + i_end(viable_children.end()) ; i != i_end ; ++i) + { + Save<bool> save_check(&_implementation->check_existing_only, true); + Save<bool> save_match(&_implementation->match_found, true); + add(*i); + if ((found = _implementation->match_found)) + break; + } + if (found) + return; + + if (_implementation->check_existing_only) + { + _implementation->match_found = false; + return; + } + + /* try to merge each of our viable children in turn. */ + for (CompositeDepAtom::Iterator i(viable_children.begin()), i_end(viable_children.end()) ; + i != i_end ; ++i) + { + try + { + add(*i); + return; + } + catch (const DepListStackTooDeepError &) + { + /* don't work around a stack too deep error. our item may be + * resolvable with a deeper stack. */ + throw; + } + catch (const DepListError &) + { + } + } + + /* no match */ + throw NoResolvableOptionError(); +} + +void +DepList::visit(const BlockDepAtom * const d) +{ + Context context("When checking block '!" + stringify(*(d->blocked_atom())) + "':"); + + /* special case: the provider of virtual/blah can DEPEND upon !virtual/blah. */ + /// \bug This may have issues if a virtual is provided by a virtual... + + PackageDatabaseEntryCollection::ConstPointer q(0); + std::list<DepListEntry>::const_iterator m; + + /* are we already installed? */ + if (! ((q = _implementation->environment->installed_db()->query(d->blocked_atom())))->empty()) + { + if (! _implementation->current_package) + throw BlockError("'" + stringify(*(d->blocked_atom())) + "' blocked by installed package '" + + stringify(*q->begin()) + "'"); + + VersionMetadata::ConstPointer metadata( + _implementation->environment->installed_db()->fetch_metadata( + *_implementation->current_package)); + if (metadata->end_provide() == std::find( + metadata->begin_provide(), metadata->end_provide(), + d->blocked_atom()->package())) + throw BlockError("'" + stringify(*(d->blocked_atom())) + "' blocked by installed package '" + + stringify(*q->begin()) + "'"); + } + + /* will we be installed by this point? */ + if (_implementation->merge_list.end() != ((m = std::find_if( + _implementation->merge_list.begin(), _implementation->merge_list.end(), + DepListEntryMatcher(*(d->blocked_atom())))))) + { + if (! _implementation->current_package) + throw BlockError("'" + stringify(*(d->blocked_atom())) + "' blocked by pending package '" + + stringify(*m)); + + VersionMetadata::ConstPointer metadata(_implementation->environment->package_db()->fetch_metadata( + *_implementation->current_package)); + if (metadata->end_provide() == std::find( + metadata->begin_provide(), metadata->end_provide(), + d->blocked_atom()->package())) + throw BlockError("'" + stringify(*(d->blocked_atom())) + "' blocked by pending package '" + + stringify(*m) + "' ~ " + join(metadata->begin_provide(), metadata->end_provide(), " ~ ")); + } +} + +void +DepList::set_rdepend_post(const bool value) +{ + _implementation->rdepend_post = value; +} + +void +DepList::set_drop_circular(const bool value) +{ + _implementation->drop_circular = value; +} + +void +DepList::set_drop_self_circular(const bool value) +{ + _implementation->drop_self_circular = value; +} + +void +DepList::set_ignore_installed(const bool value) +{ + _implementation->ignore_installed = value; +} + +void +DepList::set_recursive_deps(const bool value) +{ + _implementation->recursive_deps = value; +} + +void +DepList::set_max_stack_depth(const int value) +{ + _implementation->max_stack_depth = value; +} + diff --git a/paludis/dep_list.hh b/paludis/dep_list.hh new file mode 100644 index 000000000..e3dcf8b6b --- /dev/null +++ b/paludis/dep_list.hh @@ -0,0 +1,124 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_LIST_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LIST_HH 1 + +#include <paludis/instantiation_policy.hh> +#include <paludis/private_implementation_pattern.hh> +#include <paludis/dep_atom.hh> +#include <paludis/environment.hh> +#include <paludis/dep_atom_visitor.hh> +#include <paludis/dep_list_entry.hh> +#include <list> + +namespace paludis +{ + /** + * Holds a list of dependencies in merge order. + */ + class DepList : + private InstantiationPolicy<DepList, instantiation_method::NonCopyableTag>, + private PrivateImplementationPattern<DepList>, + protected DepAtomVisitor, + protected VisitsComposite<DepList, AllDepAtom> + { + friend class VisitsComposite<DepList, AllDepAtom>; + + private: + void _add_in_role(DepAtom::ConstPointer, const std::string & role); + + protected: + void visit(const PackageDepAtom * const); + void visit(const UseDepAtom * const); + void visit(const AnyDepAtom * const); + void visit(const BlockDepAtom * const); + + void enter(const AllDepAtom * const); + void leave(const AllDepAtom * const); + + public: + /** + * Iterator for our children. + */ + typedef std::list<DepListEntry>::const_iterator Iterator; + + /** + * Constructor. + */ + DepList(const Environment * const); + + /** + * Destructor. + */ + virtual ~DepList(); + + /** + * Add the packages required to resolve an additional dependency + * atom. + */ + void add(DepAtom::ConstPointer); + + /** + * Start of our dependency list. + */ + Iterator begin() const; + + /** + * One past the end of our dependency list. + */ + Iterator end() const; + + /** + * Behaviour: if set, RDEPEND entries can be treated as PDEPEND + * where necessary. + */ + void set_rdepend_post(const bool value); + + /** + * Behaviour: if set, a package that depends directly upon itself + * will be accepted. + */ + void set_drop_self_circular(const bool value); + + /** + * Behaviour: if set, any circular dependencies are treated as if + * they do not exist. + */ + void set_drop_circular(const bool value); + + /** + * Behaviour: ignore installed packages. + */ + void set_ignore_installed(const bool value); + + /** + * Behaviour: check nth level dependencies for packages that are + * already installed. + */ + void set_recursive_deps(const bool value); + + /** + * Behaviour: set the maximum stack depth. + */ + void set_max_stack_depth(const int value); + }; +} + +#endif diff --git a/paludis/dep_list_TEST.cc b/paludis/dep_list_TEST.cc new file mode 100644 index 000000000..36c7c7965 --- /dev/null +++ b/paludis/dep_list_TEST.cc @@ -0,0 +1,614 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace paludis; +using namespace test; + +namespace test_cases +{ + /** + * \test Test dep list: one package. + * + * \ingroup Test + */ + struct DepListOnePackageTest : TestCase + { + DepListOnePackageTest() : TestCase("one package") { } + + void run() + { + TestEnvironment e; + + /* t/one exists */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"); + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + TEST_CHECK(d.begin() != d.end()); + TEST_CHECK_EQUAL(std::distance(d.begin(), d.end()), 1); + TEST_CHECK_EQUAL(*d.begin(), DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + } + } test_dep_list_one_package; + + /** + * \test Test dep list: one installed package. + * + * \ingroup Test + */ + struct DepListOneInstalledPackageTest : TestCase + { + DepListOneInstalledPackageTest() : TestCase("one installed package") { } + + void run() + { + TestEnvironment e; + + /* t/one exists and is already installed. */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"); + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + installed->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("0.9"))-> + set(vmk_slot, "slot1"); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + TEST_CHECK(d.begin() == d.end()); + } + } test_dep_list_one_installed_package; + + /** + * \test Test dep list: dep. + * + * \ingroup Test + */ + struct DepListDepTest : TestCase + { + DepListDepTest() : TestCase("dep") { } + + void run() + { + TestEnvironment e; + + /* t/one DEPENDs upon t/two */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(vmk_depend, "t/two"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("two")), + VersionSpec("1.0"), SlotName("slot2"), RepositoryName("repo"))); + TEST_CHECK(++di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_dep; + + /** + * \test Test dep list: pdep. + * + * \ingroup Test + */ + struct DepListPDepTest : TestCase + { + DepListPDepTest() : TestCase("pdep") { } + + void run() + { + TestEnvironment e; + + /* t/one PDEPENDs upon t/two */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(vmk_pdepend, "t/two"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + TEST_CHECK(++di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("two")), + VersionSpec("1.0"), SlotName("slot2"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_pdep; + + /** + * \test Test dep list: common deps. + * + * \ingroup Test + */ + struct DepListCommonDepsTest : TestCase + { + DepListCommonDepsTest() : TestCase("common deps") { } + + void run() + { + TestEnvironment e; + + /* t/one DEPENDs upon ( t/two t/three ) ; t/two DEPENDs upon t/three */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(vmk_depend, "t/two t/three"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"). + set(vmk_depend, "t/three"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0"))-> + set(vmk_slot, "slot3"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("three")), + VersionSpec("1.0"), SlotName("slot3"), RepositoryName("repo"))); + TEST_CHECK(++di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("two")), + VersionSpec("1.0"), SlotName("slot2"), RepositoryName("repo"))); + TEST_CHECK(++di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_common_deps; + + /** + * \test Test dep list: dep failure. + * + * \ingroup Test + */ + struct DepListDepFailureTest : TestCase + { + DepListDepFailureTest() : TestCase("dep failure") { } + + void run_d(VersionMetadataKey dep_kind) + { + TestMessageSuffix suffix(stringify(dep_kind), true); + TestEnvironment e; + + /* t/one DEPENDs upon t/two and t/three. t/three has unresolvable + * deps. */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(dep_kind, "t/two t/three"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0"))-> + set(vmk_slot, "slot3"). + set(dep_kind, "t/bad"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + TEST_CHECK_THROWS(d.add(DepParser::parse("t/one")), Exception); + TEST_CHECK(d.begin() == d.end()); + + /* try again, with some stuff already in the dep list. */ + d.add(DepParser::parse("t/two")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("two")), + VersionSpec("1.0"), SlotName("slot2"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + + TEST_CHECK_THROWS(d.add(DepParser::parse("t/one")), Exception); + di = d.begin(); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("two")), + VersionSpec("1.0"), SlotName("slot2"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + + void run() + { + run_d(vmk_depend); + run_d(vmk_rdepend); + run_d(vmk_pdepend); + } + } test_dep_list_dep_failure; + + /** + * \test Test dep list: indirect circular deps. + * + * \ingroup Test + */ + struct DepListIndirectCircularDepTest : TestCase + { + DepListIndirectCircularDepTest() : TestCase("indirect circular deps") { } + + void run() + { + TestEnvironment e; + + /* t/one DEPENDs upon t/two. t/two DEPENDs upon t/three. t/three DEPENDs + * upon t/two */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(vmk_depend, "t/two"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"). + set(vmk_depend, "t/three"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0"))-> + set(vmk_slot, "slot3"). + set(vmk_depend, "t/two"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + TEST_CHECK_THROWS(d.add(DepParser::parse("t/one")), CircularDependencyError); + TEST_CHECK(d.begin() == d.end()); + + installed->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0")); + d.add(DepParser::parse("t/one")); + + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("two")), + VersionSpec("1.0"), SlotName("slot2"), RepositoryName("repo"))); + TEST_CHECK(++di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_indirect_circular_deps; + + /** + * \test Test dep list: self circular deps. + * + * \ingroup Test + */ + struct DepListSelfCircularDepTest : TestCase + { + DepListSelfCircularDepTest() : TestCase("self circular deps") { } + + void run() + { + TestEnvironment e; + + /* t/one DEPENDs upon t/two. t/two DEPENDs upon t/two. */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(vmk_depend, "t/two"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"). + set(vmk_depend, "t/two"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + TEST_CHECK_THROWS(d.add(DepParser::parse("t/one")), CircularDependencyError); + TEST_CHECK(d.begin() == d.end()); + + installed->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0")); + d.add(DepParser::parse("t/one")); + + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_self_circular_deps; + + /** + * \test Test dep list: met or dep. + * + * \ingroup Test + */ + struct DepListMetOrDepTest : TestCase + { + DepListMetOrDepTest() : TestCase("met or dep") { } + + void run() + { + TestEnvironment e; + + /* t/one DEPENDs upon || ( t/two t/three ). t/three is already + * installed */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "slot1"). + set(vmk_depend, "|| ( t/two t/three )"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + + installed->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0"))-> + set(vmk_slot, "slot2"); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("slot1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_met_or_dep; + + /** + * \test Test dep list: complex met or dep. + * + * \ingroup Test + */ + struct DepListComplexMetOrDepTest : TestCase + { + DepListComplexMetOrDepTest() : TestCase("complex met or dep") { } + + void run_n(int n) + { + TestEnvironment e; + TestMessageSuffix(stringify(n), true); + + /* t/one DEPENDs upon + * || ( + * ( t/two t/three ) + * ( + * t/four + * || ( + * t/five + * ( t/six t/seven ) + * ) + * ) + * ) + */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "1"). + set(vmk_depend, "|| ( ( t/two t/three ) ( t/four || ( t/five ( t/six t/seven ) ) ) )"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + + if (n == 1) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0")); + installed->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0")); + } + else if (n == 2) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("four"), VersionSpec("1.0")); + installed->add_version(CategoryNamePart("t"), PackageNamePart("five"), VersionSpec("1.0")); + } + else if (n == 3) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("four"), VersionSpec("1.0")); + installed->add_version(CategoryNamePart("t"), PackageNamePart("six"), VersionSpec("1.0")); + installed->add_version(CategoryNamePart("t"), PackageNamePart("seven"), VersionSpec("1.0")); + } + + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + + void run() + { + for (int n = 1 ; n <= 3 ; ++n) + run_n(n); + } + } test_dep_list_complex_met_or_dep; + + /** + * \test Test dep list: complex unmet or dep. + * + * \ingroup Test + */ + struct DepListComplexUnmetOrDepTest : TestCase + { + DepListComplexUnmetOrDepTest() : TestCase("complex unmet or dep") { } + + void run_n(int n) + { + TestEnvironment e; + TestMessageSuffix suffix(stringify(n), true); + + /* t/one DEPENDs upon + * || ( + * ( t/two t/three ) + * ( + * t/four + * || ( + * t/five + * ( t/six t/seven ) + * ) + * ) + * ) + */ + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "1"). + set(vmk_depend, "|| ( ( t/two t/three ) ( t/four || ( t/five ( t/six t/seven ) ) ) )"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + + if (n == 1) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0")); + } + else if (n == 2) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0")); + } + else if (n == 3) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("five"), VersionSpec("1.0")); + } + else if (n == 4) + { + installed->add_version(CategoryNamePart("t"), PackageNamePart("four"), VersionSpec("1.0")); + installed->add_version(CategoryNamePart("t"), PackageNamePart("seven"), VersionSpec("1.0")); + } + + e.installed_db()->add_repository(installed); + + DepList d(&e); + TEST_CHECK(d.begin() == d.end()); + TEST_CHECK_THROWS(d.add(DepParser::parse("t/one")), DepListError); + TEST_CHECK(d.begin() == d.end()); + } + + void run() + { + for (int n = 1 ; n <= 4 ; ++n) + run_n(n); + } + } test_dep_list_complex_unmet_or_dep; + + /** + * \test Test dep list: or all use dep. + * + * \ingroup Test + */ + struct DepListOrAllUseDepTest : TestCase + { + DepListOrAllUseDepTest() : TestCase("or all use dep") { } + + void run() + { + TestEnvironment e; + + FakeRepository::Pointer repo(new FakeRepository(RepositoryName("repo"))); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("one"), VersionSpec("1.0"))-> + set(vmk_slot, "1"). + set(vmk_depend, "|| ( t/two ( off? ( t/three ) ) )"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("two"), VersionSpec("1.0"))-> + set(vmk_slot, "1"); + + repo->add_version(CategoryNamePart("t"), PackageNamePart("three"), VersionSpec("1.0"))-> + set(vmk_slot, "1"); + + e.package_db()->add_repository(repo); + + FakeRepository::Pointer installed(new FakeRepository(RepositoryName("installed"))); + e.installed_db()->add_repository(installed); + + DepList d(&e); + d.add(DepParser::parse("t/one")); + DepList::Iterator di(d.begin()), di_end(d.end()); + TEST_CHECK(di != di_end); + TEST_CHECK_EQUAL(*di, DepListEntry( + QualifiedPackageName(CategoryNamePart("t"), PackageNamePart("one")), + VersionSpec("1.0"), SlotName("1"), RepositoryName("repo"))); + TEST_CHECK(++di == di_end); + } + } test_dep_list_or_all_use; + +} + diff --git a/paludis/dep_list_entry.cc b/paludis/dep_list_entry.cc new file mode 100644 index 000000000..6a6e34b27 --- /dev/null +++ b/paludis/dep_list_entry.cc @@ -0,0 +1,31 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_list_entry.hh" + +using namespace paludis; + +std::ostream & +paludis::operator<< (std::ostream & s, const DepListEntry & e) +{ + s << e.get<dle_name>() << "-" << e.get<dle_version>() << ":" + << e.get<dle_slot>() << "::" << e.get<dle_repository>(); + return s; +} + diff --git a/paludis/dep_list_entry.hh b/paludis/dep_list_entry.hh new file mode 100644 index 000000000..72524dba0 --- /dev/null +++ b/paludis/dep_list_entry.hh @@ -0,0 +1,67 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_LIST_ENTRY_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LIST_ENTRY_HH 1 + +#include <paludis/smart_record.hh> +#include <paludis/qualified_package_name.hh> +#include <paludis/version_spec.hh> +#include <paludis/slot_name.hh> +#include <paludis/repository_name.hh> +#include <ostream> + +namespace paludis +{ + /** + * Keys for a DepListEntry. + */ + enum DepListEntryKeys + { + dle_name, ///< Package name + dle_version, ///< Package version + dle_slot, ///< Package SLOT + dle_repository ///< Repository name + }; + + /** + * Tag for a DepListEntry. + */ + struct DepListEntryTag : + SmartRecordTag<comparison_mode::FullComparisonTag, comparison_method::SmartRecordCompareByAllTag>, + SmartRecordKeys<DepListEntryKeys, 4>, + SmartRecordKey<dle_name, QualifiedPackageName>, + SmartRecordKey<dle_version, VersionSpec>, + SmartRecordKey<dle_slot, SlotName>, + SmartRecordKey<dle_repository, RepositoryName> + { + }; + + /** + * A DepListEntry represents an entry in a DepList. + */ + typedef MakeSmartRecord<DepListEntryTag>::Type DepListEntry; + + /** + * A DepListEntry can be written to a stream. + */ + std::ostream & operator<< (std::ostream &, const DepListEntry &); +} + +#endif diff --git a/paludis/dep_list_error.cc b/paludis/dep_list_error.cc new file mode 100644 index 000000000..40ca8e03b --- /dev/null +++ b/paludis/dep_list_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_list_error.hh" + +using namespace paludis; + +DepListError::DepListError(const std::string & m) throw () : + Exception(m) +{ +} + diff --git a/paludis/dep_list_error.hh b/paludis/dep_list_error.hh new file mode 100644 index 000000000..64d96ceef --- /dev/null +++ b/paludis/dep_list_error.hh @@ -0,0 +1,40 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_LIST_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LIST_ERROR_HH 1 + +#include <paludis/exception.hh> + +namespace paludis +{ + /** + * Thrown if an error occurs whilst building a DepList. + */ + class DepListError : public Exception + { + protected: + /** + * Constructor. + */ + DepListError(const std::string &) throw (); + }; +} + +#endif diff --git a/paludis/dep_list_stack_too_deep_error.cc b/paludis/dep_list_stack_too_deep_error.cc new file mode 100644 index 000000000..fc3ca03dc --- /dev/null +++ b/paludis/dep_list_stack_too_deep_error.cc @@ -0,0 +1,30 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_stack_too_deep_error.hh" +#include "stringify.hh" + +using namespace paludis; + +DepListStackTooDeepError::DepListStackTooDeepError(int level) throw () : + DepListError("DepList stack too deep (" + stringify(level) + " entries)") +{ +} + diff --git a/paludis/dep_list_stack_too_deep_error.hh b/paludis/dep_list_stack_too_deep_error.hh new file mode 100644 index 000000000..1aa64c311 --- /dev/null +++ b/paludis/dep_list_stack_too_deep_error.hh @@ -0,0 +1,41 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_STACK_TOO_DEEP_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_LIST_STACK_TOO_DEEP_ERROR_HH 1 + +#include <paludis/dep_list_error.hh> + +namespace paludis +{ + /** + * Thrown if a DepList's add stack gets too deep. + */ + class DepListStackTooDeepError : public DepListError + { + public: + /** + * Constructor. + */ + DepListStackTooDeepError(int level) throw (); + }; +} + +#endif diff --git a/paludis/dep_parser.cc b/paludis/dep_parser.cc new file mode 100644 index 000000000..4729c0cfc --- /dev/null +++ b/paludis/dep_parser.cc @@ -0,0 +1,267 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "exception.hh" +#include "internal_error.hh" +#include "stringify.hh" +#include "dep_string_parse_error.hh" +#include "dep_string_nesting_error.hh" +#include "dep_parser.hh" +#include "dep_lexer.hh" +#include "all_dep_atom.hh" +#include "any_dep_atom.hh" +#include "use_dep_atom.hh" +#include "block_dep_atom.hh" +#include "package_dep_atom.hh" +#include "dep_atom_visitor.hh" +#include <stack> + +using namespace paludis; + +enum DepParserState +{ + dps_initial, + dps_had_double_bar, + dps_had_double_bar_space, + dps_had_paren, + dps_had_use_flag, + dps_had_use_flag_space +}; + +CompositeDepAtom::ConstPointer +DepParser::parse(const std::string & s) +{ + Context context("When parsing dependency string '" + s + "':"); + + std::stack<CompositeDepAtom::Pointer> stack; + stack.push(CompositeDepAtom::Pointer(new AllDepAtom)); + + DepParserState state(dps_initial); + DepLexer lexer(s); + DepLexer::Iterator i(lexer.begin()), i_end(lexer.end()); + + for ( ; i != i_end ; ++i) + { + Context context("When handling lexer token '" + i->second + + "' (" + stringify(i->first) + "):"); + do + { + switch (state) + { + case dps_initial: + do + { + switch (i->first) + { + case dpl_whitespace: + continue; + + case dpl_package: + { + if (i->second.empty()) + throw DepStringParseError(i->second, "Empty package name"); + if ('!' == i->second.at(0)) + stack.top()->add_child(DepAtom::Pointer( + new BlockDepAtom( + PackageDepAtom::Pointer(new PackageDepAtom( + i->second.substr(1)))))); + else + stack.top()->add_child(DepAtom::Pointer( + new PackageDepAtom(i->second))); + } + continue; + + case dpl_open_paren: + { + CompositeDepAtom::Pointer a(new AllDepAtom); + stack.top()->add_child(a); + stack.push(a); + state = dps_had_paren; + } + continue; + + case dpl_close_paren: + if (stack.empty()) + throw DepStringNestingError(s); + stack.pop(); + if (stack.empty()) + throw DepStringNestingError(s); + state = dps_had_paren; + continue; + + case dpl_double_bar: + { + CompositeDepAtom::Pointer a(new AnyDepAtom); + stack.top()->add_child(a); + stack.push(a); + state = dps_had_double_bar; + } + continue; + + case dpl_use_flag: + { + std::string f(i->second); + bool inv(f.length() && ('!' == f.at(0))); + if (inv) + f.erase(0, 1); + + if (f.empty()) + throw DepStringParseError(s, + "Bad use flag name '" + i->second + "'"); + if ('?' != f.at(f.length() - 1)) + throw DepStringParseError(s, + "Use flag name '" + i->second + "' missing '?'"); + + f.erase(f.length() - 1); + CompositeDepAtom::Pointer a( + new UseDepAtom(UseFlagName(f), inv)); + stack.top()->add_child(a); + stack.push(a); + state = dps_had_use_flag; + } + continue; + + } + throw InternalError(__PRETTY_FUNCTION__, + "dps_initial: i->first is " + stringify(i->first)); + + } while (0); + continue; + + case dps_had_double_bar: + do + { + switch (i->first) + { + case dpl_whitespace: + state = dps_had_double_bar_space; + continue; + + case dpl_package: + case dpl_use_flag: + case dpl_double_bar: + case dpl_open_paren: + case dpl_close_paren: + throw DepStringParseError(s, "Expected space after '||'"); + } + throw InternalError(__PRETTY_FUNCTION__, + "dps_had_double_bar: i->first is " + stringify(i->first)); + + } while (0); + continue; + + case dps_had_double_bar_space: + do + { + switch (i->first) + { + case dpl_open_paren: + state = dps_initial; + continue; + + case dpl_whitespace: + case dpl_package: + case dpl_use_flag: + case dpl_double_bar: + case dpl_close_paren: + throw DepStringParseError(s, "Expected '(' after '|| '"); + } + throw InternalError(__PRETTY_FUNCTION__, + "dps_had_double_bar_space: i->first is " + stringify(i->first)); + } while (0); + continue; + + case dps_had_paren: + do + { + switch (i->first) + { + case dpl_whitespace: + state = dps_initial; + continue; + + case dpl_package: + case dpl_use_flag: + case dpl_double_bar: + case dpl_open_paren: + case dpl_close_paren: + throw DepStringParseError(s, "Expected space after '(' or ')'"); + } + throw InternalError(__PRETTY_FUNCTION__, + "dps_had_paren: i->first is " + stringify(i->first)); + } while (0); + continue; + + case dps_had_use_flag: + do + { + switch (i->first) + { + case dpl_whitespace: + state = dps_had_use_flag_space; + continue; + + case dpl_package: + case dpl_use_flag: + case dpl_double_bar: + case dpl_open_paren: + case dpl_close_paren: + throw DepStringParseError(s, "Expected space after use flag"); + } + throw InternalError(__PRETTY_FUNCTION__, + "dps_had_use_flag: i->first is " + stringify(i->first)); + } while (0); + continue; + + case dps_had_use_flag_space: + do + { + switch (i->first) + { + case dpl_open_paren: + state = dps_had_paren; + continue; + + case dpl_whitespace: + case dpl_package: + case dpl_use_flag: + case dpl_double_bar: + case dpl_close_paren: + throw DepStringParseError(s, "Expected '(' after use flag"); + } + throw InternalError(__PRETTY_FUNCTION__, + "dps_had_use_flag_space: i->first is " + stringify(i->first)); + } while (0); + continue; + } + throw InternalError(__PRETTY_FUNCTION__, + "state is " + stringify(state)); + + } while (0); + } + + if (stack.empty()) + throw DepStringNestingError(s); + CompositeDepAtom::Pointer result(stack.top()); + stack.pop(); + if (! stack.empty()) + throw DepStringNestingError(s); + return result; +} + diff --git a/paludis/dep_parser.hh b/paludis/dep_parser.hh new file mode 100644 index 000000000..b8f800dfe --- /dev/null +++ b/paludis/dep_parser.hh @@ -0,0 +1,52 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_PARSER_HH +#define PALUDIS_GUARD_PALUDIS_DEP_PARSER_HH 1 + +#include <paludis/composite_dep_atom.hh> +#include <paludis/counted_ptr.hh> +#include <paludis/instantiation_policy.hh> +#include <string> + +/** \file + * Declarations for the DepParser class. + * + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * The DepParser converts string representations of a dependency + * specification into a DepAtom instance. + */ + class DepParser : + private InstantiationPolicy<DepParser, instantiation_method::NonInstantiableTag> + { + public: + /** + * Parse a given dependency string, and return an appropriate + * DepAtom tree. + */ + static CompositeDepAtom::ConstPointer parse(const std::string & s); + }; +} + +#endif diff --git a/paludis/dep_parser_TEST.cc b/paludis/dep_parser_TEST.cc new file mode 100644 index 000000000..da88d67af --- /dev/null +++ b/paludis/dep_parser_TEST.cc @@ -0,0 +1,245 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 <test/test_framework.hh> +#include <test/test_runner.hh> +#include "paludis.hh" +#include <sstream> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for DepParser. + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Test DepParser with an empty input. + * + * \ingroup Test + */ + struct DepParserEmptyTest : TestCase + { + DepParserEmptyTest() : TestCase("empty") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse("")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all></all>"); + } + } test_dep_atom_parser_empty; + + /** + * \test Test DepParser with a blank input. + * + * \ingroup Test + */ + struct DepParserBlankTest : TestCase + { + DepParserBlankTest() : TestCase("blank") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse(" \n \t")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all></all>"); + } + } test_dep_atom_parser_blank; + + /** + * \test Test DepParser with a package. + * + * \ingroup Test + */ + struct DepParserPackageTest : TestCase + { + DepParserPackageTest() : TestCase("package") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse("app-editors/vim")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><package>app-editors/vim</package></all>"); + } + } test_dep_atom_parser_package; + + /** + * \test Test DepParser with a decorated package. + * + * \ingroup Test + */ + struct DepParserDecoratedPackageTest : TestCase + { + DepParserDecoratedPackageTest() : TestCase("decorated package") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse(">=app-editors/vim-6.4_alpha")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><package version=\">=6.4_alpha\">" + "app-editors/vim</package></all>"); + } + } test_dep_atom_parser_decorated_package; + + /** + * \test Test DepParser with a sequence of packages. + * + * \ingroup Test + */ + struct DepParserPackagesTest : TestCase + { + DepParserPackagesTest() : TestCase("packages") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse("app-editors/vim app-misc/hilite \nsys-apps/findutils")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><package>app-editors/vim</package>" + "<package>app-misc/hilite</package><package>sys-apps/findutils</package></all>"); + } + } test_dep_atom_parser_packages; + + /** + * \test Test DepParser with an any group. + * + * \ingroup Test + */ + struct DepParserAnyTest : TestCase + { + DepParserAnyTest() : TestCase("any") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse("|| ( one/one two/two )")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><any><package>one/one</package>" + "<package>two/two</package></any></all>"); + } + } test_dep_atom_parser_any; + + /** + * \test Test DepParser with an all group. + * + * \ingroup Test + */ + struct DepParserAllTest : TestCase + { + DepParserAllTest() : TestCase("all") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse(" ( one/one two/two ) ")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><all><package>one/one</package>" + "<package>two/two</package></all></all>"); + } + } test_dep_atom_parser_all; + + /** + * \test Test DepParser with a use group. + * + * \ingroup Test + */ + struct DepParserUseTest : TestCase + { + DepParserUseTest() : TestCase("use") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse("foo? ( one/one )")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><use flag=\"foo\" inverse=\"false\"><package>one/one</package>" + "</use></all>"); + } + } test_dep_atom_parser_use; + + /** + * \test Test DepParser with an inverse use group. + * + * \ingroup Test + */ + struct DepParserInvUseTest : TestCase + { + DepParserInvUseTest() : TestCase("!use") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + DepParser::parse("!foo? ( one/one )")->accept(&d); + TEST_CHECK_EQUAL(s.str(), "<all><use flag=\"foo\" inverse=\"true\"><package>one/one</package>" + "</use></all>"); + } + } test_dep_atom_parser_inv_use; + + /** + * \test Test DepParser nesting errors. + * + * \ingroup Test + */ + struct DepParserBadNestingTest : TestCase + { + DepParserBadNestingTest() : TestCase("bad nesting") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + TEST_CHECK_THROWS(DepParser::parse("!foo? ( one/one")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse("!foo? ( one/one ) )")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse("( ( ( ) )")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse("( ( ( ) ) ) )")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse(")")->accept(&d), DepStringError); + } + } test_dep_atom_parser_bad_nesting; + + /** + * \test Test DepParser weird errors. + * + * \ingroup Test + */ + struct DepParserBadValuesTest : TestCase + { + DepParserBadValuesTest() : TestCase("bad values") { } + + void run() + { + std::stringstream s; + DepAtomDumper d(&s); + TEST_CHECK_THROWS(DepParser::parse("!foo? ||")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse("(((")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse(")")->accept(&d), DepStringError); + TEST_CHECK_THROWS(DepParser::parse("(foo/bar)")->accept(&d), DepStringError); + } + } test_dep_atom_parser_bad_values; +} + diff --git a/paludis/dep_string_error.cc b/paludis/dep_string_error.cc new file mode 100644 index 000000000..5f9e10ee5 --- /dev/null +++ b/paludis/dep_string_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_string_error.hh" + +using namespace paludis; + +DepStringError::DepStringError(const std::string & d, const std::string & m) throw () : + Exception("Bad dependency string '" + d + "': " + m) +{ +} + diff --git a/paludis/dep_string_error.hh b/paludis/dep_string_error.hh new file mode 100644 index 000000000..a95706e10 --- /dev/null +++ b/paludis/dep_string_error.hh @@ -0,0 +1,52 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_STRING_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_STRING_ERROR_HH 1 + +#include <paludis/exception.hh> + +/** \file + * Declarations for DepStringError. + * + * \ingroup Exception + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * A DepStringError descendent is thrown if an invalid depend string is + * encountered. + * + * \ingroup Exception + * \ingroup DepResolver + */ + class DepStringError : public Exception + { + protected: + /** + * Constructor. + */ + DepStringError(const std::string & dep_string, + const std::string & message) throw (); + }; +} + +#endif diff --git a/paludis/dep_string_lex_error.cc b/paludis/dep_string_lex_error.cc new file mode 100644 index 000000000..38584e17d --- /dev/null +++ b/paludis/dep_string_lex_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_string_lex_error.hh" + +using namespace paludis; + +DepStringLexError::DepStringLexError(const std::string & dep_string, + const std::string & message) throw () : + DepStringError(dep_string, "in lex phase: " + message) +{ +} diff --git a/paludis/dep_string_lex_error.hh b/paludis/dep_string_lex_error.hh new file mode 100644 index 000000000..19ba3d4d4 --- /dev/null +++ b/paludis/dep_string_lex_error.hh @@ -0,0 +1,52 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_STRING_LEX_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_STRING_LEX_ERROR_HH 1 + +#include <paludis/dep_string_error.hh> + +/** \file + * Declarations for the DepStringLexError class. + * + * \ingroup Exception + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * A DepStringLexError is thrown if a lex-level error is encountered when + * parsing a dependency string. + * + * \ingroup Exception + * \ingroup DepResolver + */ + class DepStringLexError : public DepStringError + { + public: + /** + * Constructor. + */ + DepStringLexError(const std::string & dep_string, + const std::string & message) throw (); + }; +} + +#endif diff --git a/paludis/dep_string_nesting_error.cc b/paludis/dep_string_nesting_error.cc new file mode 100644 index 000000000..5b16a4fcb --- /dev/null +++ b/paludis/dep_string_nesting_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_string_nesting_error.hh" + +using namespace paludis; + +DepStringNestingError::DepStringNestingError(const std::string & dep_string) throw () : + DepStringParseError(dep_string, "improperly balanced parentheses") +{ +} + diff --git a/paludis/dep_string_nesting_error.hh b/paludis/dep_string_nesting_error.hh new file mode 100644 index 000000000..c37e60d40 --- /dev/null +++ b/paludis/dep_string_nesting_error.hh @@ -0,0 +1,48 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_STRING_NESTING_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_STRING_NESTING_ERROR_HH 1 + +#include <paludis/dep_string_parse_error.hh> + +/** \file + * Declarations for the DepStringNestingError exception. + * + * \ingroup Exception + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * A DepStringNestingError is thrown if a dependency string does not have + * properly balanced parentheses. + */ + class DepStringNestingError : public DepStringParseError + { + public: + /** + * Constructor. + */ + DepStringNestingError(const std::string & dep_string) throw (); + }; +} + +#endif diff --git a/paludis/dep_string_parse_error.cc b/paludis/dep_string_parse_error.cc new file mode 100644 index 000000000..d1aaa86d5 --- /dev/null +++ b/paludis/dep_string_parse_error.cc @@ -0,0 +1,29 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dep_string_parse_error.hh" + +using namespace paludis; + +DepStringParseError::DepStringParseError(const std::string & d, + const std::string & m) throw () : + DepStringError(d, "in parse phase: " + m) +{ +} + diff --git a/paludis/dep_string_parse_error.hh b/paludis/dep_string_parse_error.hh new file mode 100644 index 000000000..8a29a01fb --- /dev/null +++ b/paludis/dep_string_parse_error.hh @@ -0,0 +1,52 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DEP_STRING_PARSE_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DEP_STRING_PARSE_ERROR_HH 1 + +#include <paludis/dep_string_error.hh> + +/** \file + * Declarations for the DepStringParseError class. + * + * \ingroup Exception + * \ingroup DepResolver + */ + +namespace paludis +{ + /** + * A DepStringParseError is thrown if an error is encountered when parsing + * a dependency string. + * + * \ingroup Exception + * \ingroup DepResolver + */ + class DepStringParseError : public DepStringError + { + public: + /** + * Constructor. + */ + DepStringParseError(const std::string & dep_string, + const std::string & message) throw (); + }; +} + +#endif diff --git a/paludis/dir_iterator.cc b/paludis/dir_iterator.cc new file mode 100644 index 000000000..60da68a3d --- /dev/null +++ b/paludis/dir_iterator.cc @@ -0,0 +1,128 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dir_iterator.hh" +#include "dir_open_error.hh" +#include "internal_error.hh" +#include "stringify.hh" +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> + +/** \file + * Implementation of paludis::DirIterator. + * + * \ingroup Filesystem + */ + +using namespace paludis; + +DirIterator::DirIterator(const FSEntry & base) : + _base(base), + _items(new std::set<FSEntry>) +{ + DIR * d(opendir(stringify(base).c_str())); + if (0 == d) + throw DirOpenError(base, errno); + + struct dirent * de; + while (0 != ((de = readdir(d)))) + if ('.' != de->d_name[0]) + _items->insert(_base / std::string(de->d_name)); + _iter = _items->begin(); + + closedir(d); +} + +DirIterator::DirIterator(const DirIterator & other) : + _base(other._base), + _items(other._items), + _iter(other._iter) +{ +} + +DirIterator::DirIterator() : + _base(""), + _items(new std::set<FSEntry>), + _iter(_items->end()) +{ +} + +DirIterator::~DirIterator() +{ +} + +const DirIterator & +DirIterator::operator= (const DirIterator & other) +{ + if (this != &other) + { + _base = other._base; + _items = other._items; + _iter = other._iter; + } + return *this; +} + +const FSEntry & +DirIterator::operator* () const +{ + return *_iter; +} + +const FSEntry * +DirIterator::operator-> () const +{ + return &*_iter; +} + +DirIterator & +DirIterator::operator++ () +{ + ++_iter; + return *this; +} + +DirIterator +DirIterator::operator++ (int) +{ + DirIterator c(*this); + _iter++; + return c; +} + +bool +DirIterator::operator== (const DirIterator & other) const +{ + if (other._iter == other._items->end()) + return _iter == _items->end(); + + if (other._items != _items) + throw InternalError(__PRETTY_FUNCTION__, + "comparing two different DirIterators."); + + return other._iter == _iter; +} + +bool +DirIterator::operator!= (const DirIterator & other) const +{ + return ! operator== (other); +} + diff --git a/paludis/dir_iterator.hh b/paludis/dir_iterator.hh new file mode 100644 index 000000000..7a1be6cb0 --- /dev/null +++ b/paludis/dir_iterator.hh @@ -0,0 +1,110 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DIR_ITERATOR_HH +#define PALUDIS_GUARD_PALUDIS_DIR_ITERATOR_HH 1 + +#include <paludis/fs_entry.hh> +#include <paludis/counted_ptr.hh> +#include <iterator> +#include <set> + +/** \file + * Declarations for paludis::DirIterator. + * + * \ingroup Filesystem + */ + +namespace paludis +{ + /** + * An iterator that iterates over the contents of a directory. At present, + * we read in all the entries at creation time and maintain a CountedPtr + * to an ordered set of FSEntry instances. This may change at some point, + * if it turns out that it's quicker to use opendir and seekdir for each + * instance. + * + * \ingroup Filesystem + */ + class DirIterator : public std::iterator<std::forward_iterator_tag, FSEntry> + { + private: + FSEntry _base; + CountedPtr<std::set<FSEntry>, count_policy::ExternalCountTag> _items; + std::set<FSEntry>::iterator _iter; + + public: + /** + * Constructor, to an FSEntry which must be a directory. + */ + explicit DirIterator(const FSEntry & base); + + /** + * Copy constructor. + */ + DirIterator(const DirIterator & other); + + /** + * Constructor, creates an end() iterator. + */ + DirIterator(); + + /** + * Destructor. + */ + ~DirIterator(); + + /** + * Assign. + */ + const DirIterator & operator= (const DirIterator & other); + + /** + * Dereference. + */ + const FSEntry & operator* () const; + + /** + * Dereference. + */ + const FSEntry * operator-> () const; + + /** + * Increment. + */ + DirIterator & operator++ (); + + /** + * Increment. + */ + DirIterator operator++ (int); + + /** + * Compare. + */ + bool operator== (const DirIterator & other) const; + + /** + * Inverse compare. + */ + bool operator!= (const DirIterator & other) const; + }; +} + +#endif diff --git a/paludis/dir_open_error.cc b/paludis/dir_open_error.cc new file mode 100644 index 000000000..550204dbb --- /dev/null +++ b/paludis/dir_open_error.cc @@ -0,0 +1,29 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "dir_open_error.hh" +#include "stringify.hh" + +using namespace paludis; + +DirOpenError::DirOpenError(const FSEntry & location, const int errno_value) throw () : + FSError("Error opening directory '" + stringify(location) + "': " + strerror(errno_value)) +{ +} + diff --git a/paludis/dir_open_error.hh b/paludis/dir_open_error.hh new file mode 100644 index 000000000..743b94a30 --- /dev/null +++ b/paludis/dir_open_error.hh @@ -0,0 +1,49 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DIR_OPEN_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DIR_OPEN_ERROR_HH 1 + +#include <paludis/fs_error.hh> +#include <paludis/fs_entry.hh> + +/** \file + * Declarations for DirOpenError. + * + * \ingroup Exception + */ + +namespace paludis +{ + /** + * Raised when a directory open fails. + * + * \ingroup Exception + */ + class DirOpenError : public FSError + { + public: + /** + * Constructor. + */ + DirOpenError(const FSEntry & location, const int errno_value) throw (); + }; +} + +#endif diff --git a/paludis/duplicate_repository_error.cc b/paludis/duplicate_repository_error.cc new file mode 100644 index 000000000..ee379af11 --- /dev/null +++ b/paludis/duplicate_repository_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "duplicate_repository_error.hh" + +using namespace paludis; + +DuplicateRepositoryError::DuplicateRepositoryError(const std::string & name) throw () : + PackageDatabaseError("A repository named '" + name + "' already exists") +{ +} + diff --git a/paludis/duplicate_repository_error.hh b/paludis/duplicate_repository_error.hh new file mode 100644 index 000000000..8776a4fd5 --- /dev/null +++ b/paludis/duplicate_repository_error.hh @@ -0,0 +1,45 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_DUPLICATE_REPOSITORY_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_DUPLICATE_REPOSITORY_ERROR_HH 1 + +#include <paludis/package_database_error.hh> + +/** \file + * Declarations for the DuplicateRepositoryError class. + */ + +namespace paludis +{ + /** + * Thrown if a Repository with the same name as an existing member is added + * to a PackageDatabase. + */ + class DuplicateRepositoryError : public PackageDatabaseError + { + public: + /** + * Constructor. + */ + DuplicateRepositoryError(const std::string & name) throw (); + }; +} + +#endif diff --git a/paludis/environment.cc b/paludis/environment.cc new file mode 100644 index 000000000..0c7fe7917 --- /dev/null +++ b/paludis/environment.cc @@ -0,0 +1,73 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "package_database.hh" +#include "environment.hh" +#include "internal_error.hh" + +using namespace paludis; + +Environment::Environment(PackageDatabase::Pointer d, PackageDatabase::Pointer i) : + _package_db(d), + _installed_db(i) +{ +} + +Environment::~Environment() +{ +} + +MaskReasons +Environment::mask_reasons(const PackageDatabaseEntry & e) const +{ + MaskReasons result; + VersionMetadata::ConstPointer metadata(package_db()->fetch_metadata(e)); + + if (metadata->get(vmk_eapi) != "0" && metadata->get(vmk_eapi) != "") + result.set(mr_eapi); + else + { + + result.set(mr_keyword); + for (VersionMetadata::KeywordIterator k(metadata->begin_keywords()), + k_end(metadata->end_keywords()) ; k != k_end ; ++k) + if (accept_keyword(*k, &e)) + { + result.reset(mr_keyword); + break; + } + + if (! query_user_unmasks(e)) + { + if (query_user_masks(e)) + result.set(mr_user_mask); + + if (package_db()->fetch_repository(e.get<pde_repository>())->query_profile_masks(e.get<pde_package>(), + e.get<pde_version>())) + result.set(mr_profile_mask); + + if (package_db()->fetch_repository(e.get<pde_repository>())->query_repository_masks(e.get<pde_package>(), + e.get<pde_version>())) + result.set(mr_repository_mask); + } + } + + return result; +} + diff --git a/paludis/environment.hh b/paludis/environment.hh new file mode 100644 index 000000000..5b0e4f4f2 --- /dev/null +++ b/paludis/environment.hh @@ -0,0 +1,111 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_ENVIRONMENT_HH +#define PALUDIS_GUARD_PALUDIS_ENVIRONMENT_HH 1 + +#include <paludis/package_database_entry.hh> +#include <paludis/package_database.hh> +#include <paludis/use_flag_name.hh> +#include <paludis/keyword_name.hh> +#include <paludis/instantiation_policy.hh> +#include <paludis/counted_ptr.hh> +#include <paludis/mask_reasons.hh> + +/** \file + * Declarations for the Environment class. + * + * \ingroup Environment + */ + +namespace paludis +{ + class PackageDatabase; + + /** + * Represents a working environment, which contains an available packages + * database and an installed packages database and provides various methods + * for querying package visibility and options. + * + * \ingroup Environment + */ + class Environment : + private InstantiationPolicy<Environment, instantiation_method::NonCopyableTag> + { + private: + PackageDatabase::Pointer _package_db; + PackageDatabase::Pointer _installed_db; + + protected: + /** + * Constructor. + */ + Environment(PackageDatabase::Pointer, PackageDatabase::Pointer); + + public: + /** + * Does the user want the specified USE flag set, possibly for a + * particular package? + */ + virtual bool query_use(const UseFlagName &, const PackageDatabaseEntry * const) const = 0; + + /** + * Is the specified KEYWORD accepted? + */ + virtual bool accept_keyword(const KeywordName &, const PackageDatabaseEntry * const) const = 0; + + /** + * Fetch the masks for a particular package. + */ + MaskReasons mask_reasons(const PackageDatabaseEntry &) const; + + /** + * Are there any user masks on a package? + */ + virtual bool query_user_masks(const PackageDatabaseEntry &) const = 0; + + /** + * Are there any user unmasks on a package? + */ + virtual bool query_user_unmasks(const PackageDatabaseEntry &) const = 0; + + /** + * Fetch our package database. + */ + PackageDatabase::Pointer package_db() const + { + return _package_db; + } + + /** + * Fetch our installed database. + */ + PackageDatabase::Pointer installed_db() const + { + return _installed_db; + } + + /** + * Destructor. + */ + virtual ~Environment(); + }; +} + +#endif diff --git a/paludis/exception.cc b/paludis/exception.cc new file mode 100644 index 000000000..346df8f2d --- /dev/null +++ b/paludis/exception.cc @@ -0,0 +1,38 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "exception.hh" + +using namespace paludis; + +Exception::Exception(const std::string & message) throw () : + _message(message) +{ +} + +Exception::~Exception() throw () +{ +} + +const std::string & +Exception::message() const throw () +{ + return _message; +} + diff --git a/paludis/exception.hh b/paludis/exception.hh new file mode 100644 index 000000000..b6b900324 --- /dev/null +++ b/paludis/exception.hh @@ -0,0 +1,75 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_EXCEPTION_HH +#define PALUDIS_GUARD_PALUDIS_EXCEPTION_HH 1 + +#include <paludis/attributes.hh> + +#include <string> +#include <exception> +#include <libebt/libebt.hh> + +/** \file + * Declaration for the Exception base class. + */ + +namespace paludis +{ + /** + * Context tag for libebt. + */ + struct PaludisBacktraceTag + { + }; + + /** + * Backtrace context class. + */ + typedef libebt::BacktraceContext<PaludisBacktraceTag> Context; + + /** + * Base exception class. + */ + class Exception : public std::exception, + public libebt::Backtraceable<PaludisBacktraceTag> + { + private: + const std::string _message; + + protected: + /** + * Constructor. + */ + Exception(const std::string & message) throw (); + + public: + /** + * Destructor. + */ + virtual ~Exception() throw () PALUDIS_ATTRIBUTE((nothrow)); + + /** + * Return our descriptive error message. + */ + const std::string & message() const throw () PALUDIS_ATTRIBUTE((nothrow)); + }; +} + +#endif diff --git a/paludis/fake_repository.cc b/paludis/fake_repository.cc new file mode 100644 index 000000000..b7a202ddf --- /dev/null +++ b/paludis/fake_repository.cc @@ -0,0 +1,196 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "fake_repository.hh" +#include "package_name_part_collection.hh" +#include "version_spec_collection.hh" +#include "internal_error.hh" +#include "version_metadata.hh" +#include "stringify.hh" +#include <map> + +using namespace paludis; + +namespace paludis +{ + /** + * Implementation data for FakeRepository. + */ + template<> + struct Implementation<FakeRepository> : + private InstantiationPolicy<Implementation<FakeRepository>, instantiation_method::NonCopyableTag>, + InternalCounted<Implementation<FakeRepository> > + { + /// Our category names. + CategoryNamePartCollection::Pointer category_names; + + /// Our package names. + std::map<CategoryNamePart, PackageNamePartCollection::Pointer > package_names; + + /// Our versions. + std::map<QualifiedPackageName, VersionSpecCollection::Pointer > versions; + + /// Our metadata. + std::map<std::string, VersionMetadata::Pointer > metadata; + + /// Constructor. + Implementation() : + category_names(new CategoryNamePartCollection) + { + } + }; +} + +FakeRepository::FakeRepository(const RepositoryName & name) : + Repository(name), + PrivateImplementationPattern<FakeRepository>(new Implementation<FakeRepository>) +{ + _info.insert(std::make_pair("format", "fake")); +} + +FakeRepository::~FakeRepository() +{ +} + +bool +FakeRepository::do_has_category_named(const CategoryNamePart & c) const +{ + return (_implementation->category_names->end() != _implementation->category_names->find(c)); +} + +bool +FakeRepository::do_has_package_named(const CategoryNamePart & c, + const PackageNamePart & p) const +{ + return has_category_named(c) && + (_implementation->package_names.find(c)->second->end() != + _implementation->package_names.find(c)->second->find(p)); +} + +CategoryNamePartCollection::ConstPointer +FakeRepository::do_category_names() const +{ + return _implementation->category_names; +} + +QualifiedPackageNameCollection::ConstPointer +FakeRepository::do_package_names(const CategoryNamePart & c) const +{ + if (! has_category_named(c)) + throw InternalError(__PRETTY_FUNCTION__, "no category named " + stringify(c)); + QualifiedPackageNameCollection::Pointer result(new QualifiedPackageNameCollection); + PackageNamePartCollection::Iterator p(_implementation->package_names.find(c)->second->begin()), + p_end(_implementation->package_names.find(c)->second->end()); + for ( ; p != p_end ; ++p) + result->insert(QualifiedPackageName(c, *p)); + return result; +} + +VersionSpecCollection::ConstPointer +FakeRepository::do_version_specs(const QualifiedPackageName & n) const +{ + if (! has_category_named(n.get<qpn_category>())) + throw InternalError(__PRETTY_FUNCTION__, "no category"); + if (! has_package_named(n.get<qpn_category>(), n.get<qpn_package>())) + throw InternalError(__PRETTY_FUNCTION__, "no package"); + return _implementation->versions.find(n)->second; +} + +bool +FakeRepository::do_has_version(const CategoryNamePart & c, + const PackageNamePart & p, const VersionSpec & v) const +{ + if (! has_category_named(c)) + throw InternalError(__PRETTY_FUNCTION__, "no category"); + if (! has_package_named(c, p)) + throw InternalError(__PRETTY_FUNCTION__, "no package"); + return _implementation->versions.find(QualifiedPackageName(c, p))->second->find(v) != + _implementation->versions.find(QualifiedPackageName(c, p))->second->end(); +} + +void +FakeRepository::add_category(const CategoryNamePart & c) +{ + _implementation->category_names->insert(c); + _implementation->package_names.insert(std::make_pair(c, new PackageNamePartCollection)); +} + +void +FakeRepository::add_package(const CategoryNamePart & c, const PackageNamePart & p) +{ + add_category(c); + _implementation->package_names.find(c)->second->insert(p); + _implementation->versions.insert(std::make_pair(QualifiedPackageName(c, p), + new VersionSpecCollection)); +} + +VersionMetadata::Pointer +FakeRepository::add_version(const CategoryNamePart & c, const PackageNamePart & p, + const VersionSpec & v) +{ + add_package(c, p); + _implementation->versions.find(QualifiedPackageName(c, p))->second->insert(v); + _implementation->metadata.insert( + std::make_pair(stringify(c) + "/" + stringify(p) + "-" + stringify(v), new VersionMetadata)); + VersionMetadata::Pointer r(_implementation->metadata.find(stringify(c) + + "/" + stringify(p) + "-" + stringify(v))->second); + r->set(vmk_slot, "0"); + r->set(vmk_keywords, "test"); + return r; +} + +VersionMetadata::ConstPointer +FakeRepository::do_version_metadata( + const CategoryNamePart & c, const PackageNamePart & p, const VersionSpec & v) const +{ + if (! has_version(c, p, v)) + throw InternalError(__PRETTY_FUNCTION__, "no version"); + return _implementation->metadata.find(stringify(c) + "/" + stringify(p) + "-" + stringify(v))->second; +} + +bool +FakeRepository::do_query_repository_masks(const CategoryNamePart &, + const PackageNamePart &, const VersionSpec &) const +{ + /// \todo? + return false; +} + +bool +FakeRepository::do_query_profile_masks(const CategoryNamePart &, + const PackageNamePart &, const VersionSpec &) const +{ + /// \todo? + return false; +} + +bool +FakeRepository::do_query_use(const UseFlagName &, const bool & d) const +{ + /// \todo? + return d; +} + +bool +FakeRepository::do_query_use_mask(const UseFlagName &) const +{ + /// \todo? + return false; +} + diff --git a/paludis/fake_repository.hh b/paludis/fake_repository.hh new file mode 100644 index 000000000..8abfcfa77 --- /dev/null +++ b/paludis/fake_repository.hh @@ -0,0 +1,109 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_FAKE_REPOSITORY_HH +#define PALUDIS_GUARD_PALUDIS_FAKE_REPOSITORY_HH 1 + +#include <paludis/repository.hh> +#include <paludis/private_implementation_pattern.hh> + +/** \file + * Declarations for the FakeRepository class. + * + * \ingroup Database + */ + +namespace paludis +{ + /** + * A FakeRepository is a Repository subclass that is used for + * various test cases. + * + * \ingroup Database + */ + class FakeRepository : public Repository, + private PrivateImplementationPattern<FakeRepository> + { + protected: + virtual bool do_has_category_named(const CategoryNamePart &) const; + + virtual bool do_has_package_named(const CategoryNamePart &, + const PackageNamePart &) const; + + virtual CategoryNamePartCollection::ConstPointer do_category_names() const; + + virtual QualifiedPackageNameCollection::ConstPointer do_package_names( + const CategoryNamePart &) const; + + virtual VersionSpecCollection::ConstPointer do_version_specs( + const QualifiedPackageName &) const; + + virtual bool do_has_version(const CategoryNamePart &, + const PackageNamePart &, const VersionSpec &) const; + + virtual VersionMetadata::ConstPointer do_version_metadata( + const CategoryNamePart &, const PackageNamePart &, + const VersionSpec &) const; + + virtual bool do_query_repository_masks(const CategoryNamePart &, + const PackageNamePart &, const VersionSpec &) const; + + virtual bool do_query_profile_masks(const CategoryNamePart &, + const PackageNamePart &, const VersionSpec &) const; + + virtual bool do_query_use(const UseFlagName &, const bool &) const; + + virtual bool do_query_use_mask(const UseFlagName &) const; + + public: + /** + * Constructor. + */ + FakeRepository(const RepositoryName & name); + + /** + * Destructor. + */ + + ~FakeRepository(); + + /** + * Add a category. + */ + void add_category(const CategoryNamePart &); + + /** + * Add a package, and a category if necessary. + */ + void add_package(const CategoryNamePart &, const PackageNamePart &); + + /** + * Add a version, and a package and category if necessary, and set some + * default values for its metadata, and return said metadata. + */ + VersionMetadata::Pointer add_version( + const CategoryNamePart &, const PackageNamePart &, const VersionSpec &); + + typedef CountedPtr<FakeRepository, count_policy::InternalCountTag> Pointer; + typedef CountedPtr<const FakeRepository, count_policy::InternalCountTag> ConstPointer; + }; +} + + +#endif diff --git a/paludis/files.m4 b/paludis/files.m4 new file mode 100644 index 000000000..444f877dc --- /dev/null +++ b/paludis/files.m4 @@ -0,0 +1,119 @@ +dnl vim: set ft=m4 et : +dnl This file is used by Makefile.am.m4 and paludis.hh.m4. You should +dnl use the provided autogen.bash script to do all the hard work. + +add(`about', `hh', `test') +add(`all_dep_atom', `hh', `cc') +add(`all_masked_error', `hh', `cc') +add(`ambiguous_package_name_error', `hh', `cc') +add(`any_dep_atom', `hh', `cc') +add(`attributes', `hh', `cc') +add(`bad_version_spec_error', `hh', `cc') +add(`block_dep_atom', `hh', `cc') +add(`block_error', `hh', `cc') +add(`category_name_part', `hh', `cc') +add(`category_name_part_collection', `hh', `cc') +add(`category_name_part_error', `hh', `cc') +add(`category_name_part_validator', `hh', `cc') +add(`circular_dependency_error', `hh', `cc') +add(`comparison_policy', `hh', `cc', `test') +add(`composite_dep_atom', `hh', `cc') +add(`composite_pattern', `hh', `cc') +add(`composite_visitor_pattern', `hh', `cc', `impl') +add(`config_file', `hh', `cc', `test') +add(`config_file_error', `hh', `cc') +add(`container_entry', `hh', `cc', `test') +add(`counted_ptr', `hh', `cc', `test') +add(`counted_ptr_error', `hh', `cc') +add(`create_insert_iterator', `hh', `cc', `test') +add(`default_config', `hh', `cc') +add(`default_config_error', `hh', `cc') +add(`default_environment', `hh', `cc') +add(`deleter', `hh', `cc', `test') +add(`dep_atom', `hh', `cc') +add(`dep_atom_dumper', `hh', `cc', `test') +add(`dep_atom_visitor', `hh', `cc') +add(`dep_lexer', `hh', `cc', `test') +add(`dep_list', `hh', `cc', `test') +add(`dep_list_entry', `hh', `cc') +add(`dep_list_error', `hh', `cc') +add(`dep_list_stack_too_deep_error', `hh', `cc') +add(`dep_parser', `hh', `cc', `test') +add(`dep_string_error', `hh', `cc') +add(`dep_string_lex_error', `hh', `cc') +add(`dep_string_nesting_error', `hh', `cc') +add(`dep_string_parse_error', `hh', `cc') +add(`dir_iterator', `hh', `cc') +add(`dir_open_error', `hh', `cc') +add(`duplicate_repository_error', `hh', `cc') +add(`environment', `hh', `cc') +add(`exception', `hh', `cc') +add(`fake_repository', `hh', `cc') +add(`filter_insert_iterator', `hh', `cc', `test') +add(`fs_entry', `hh', `cc', `test') +add(`fs_error', `hh', `cc') +add(`getenv', `hh', `cc', `test') +add(`indirect_iterator', `hh', `cc', `test') +add(`instantiation_policy', `hh', `cc', `test') +add(`internal_error', `hh', `cc') +add(`is_const', `hh', `cc', `test') +add(`is_file_with_extension', `hh', `cc', `test') +add(`join', `hh', `cc', `test') +add(`key_value_config_file', `hh', `cc', `test') +add(`keyword_name', `hh', `cc') +add(`keyword_name_error', `hh', `cc') +add(`keyword_name_validator', `hh', `cc') +add(`line_config_file', `hh', `cc', `test') +add(`mask_reasons', `hh', `cc') +add(`name_error', `hh', `cc') +add(`no_resolvable_option_error', `hh', `cc') +add(`no_such_package_error', `hh', `cc') +add(`no_such_repository_error', `hh', `cc') +add(`no_such_version_error', `hh', `cc') +add(`package_database', `hh', `cc', `test') +add(`package_database_entry', `hh', `cc') +add(`package_database_entry_collection', `hh', `cc') +add(`package_database_error', `hh', `cc') +add(`package_database_lookup_error', `hh', `cc') +add(`package_dep_atom', `hh', `cc') +add(`package_name_part', `hh', `cc', `test') +add(`package_name_part_collection', `hh', `cc') +add(`package_name_part_error', `hh', `cc') +add(`package_name_part_validator', `hh', `cc') +add(`paludis', `hh', `cc') +add(`portage_repository', `hh', `cc') +add(`private_implementation_pattern', `hh', `cc') +add(`pstream', `hh', `cc', `test') +add(`pstream_error', `hh', `cc') +add(`pstream_in_buf', `hh', `cc') +add(`qualified_package_name', `hh', `cc', `test') +add(`qualified_package_name_collection', `hh', `cc') +add(`qualified_package_name_error', `hh', `cc') +add(`repository', `hh', `cc') +add(`repository_name', `hh', `cc') +add(`repository_name_collection', `hh', `cc') +add(`repository_name_error', `hh', `cc') +add(`repository_name_validator', `hh', `cc') +add(`save', `hh', `cc', `test') +add(`sequential_collection', `hh', `cc') +add(`smart_record', `hh', `cc', `test') +add(`slot_name', `hh', `cc') +add(`slot_name_error', `hh', `cc') +add(`slot_name_validator', `hh', `cc') +add(`sorted_collection', `hh', `cc') +add(`stringify', `hh', `cc', `test') +add(`strip', `hh', `cc', `test') +add(`tokeniser', `hh', `cc', `test') +add(`test_environment', `hh', `cc') +add(`translate_insert_iterator', `hh', `cc', `test') +add(`use_dep_atom', `hh', `cc') +add(`use_flag_name', `hh', `cc') +add(`use_flag_name_error', `hh', `cc') +add(`use_flag_name_validator', `hh', `cc') +add(`validated', `hh', `cc', `test') +add(`version_metadata', `hh', `cc') +add(`version_operator', `hh', `cc', `test') +add(`version_spec', `hh', `cc', `test') +add(`version_spec_collection', `hh', `cc') +add(`visitor_pattern', `hh', `cc', `impl', `test') + diff --git a/paludis/filter_insert_iterator.cc b/paludis/filter_insert_iterator.cc new file mode 100644 index 000000000..8f9dafc84 --- /dev/null +++ b/paludis/filter_insert_iterator.cc @@ -0,0 +1,4 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "filter_insert_iterator.hh" + diff --git a/paludis/filter_insert_iterator.hh b/paludis/filter_insert_iterator.hh new file mode 100644 index 000000000..79324ea8c --- /dev/null +++ b/paludis/filter_insert_iterator.hh @@ -0,0 +1,113 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_FILTER_INSERT_ITERATOR_HH +#define PALUDIS_GUARD_PALUDIS_FILTER_INSERT_ITERATOR_HH 1 + +#include <functional> +#include <iterator> + +namespace paludis +{ + template <typename Iter_, typename Pred_> + class FilterInsertIterator : + public std::iterator<typename std::iterator_traits<Iter_>::iterator_category, void, void, void, void> + { + private: + Iter_ _i; + Pred_ _p; + + public: + typedef typename Iter_::container_type container_type; + + /** + * Constructor, from an iterator. + */ + FilterInsertIterator(const Iter_ & i, const Pred_ & p) : + _i(i), + _p(p) + { + } + + /** + * Copy constructor. + */ + FilterInsertIterator(const FilterInsertIterator & other) : + _i(other._i), + _p(other._p) + { + } + + /** + * Assignment. + */ + template <typename T_> + const FilterInsertIterator & operator= (const T_ value) + { + if (_p(value)) + *_i = value; + return *this; + } + + /** + * Dereference. + */ + FilterInsertIterator & operator* () + { + return *this; + } + + /** + * Dereference arrow. + */ + FilterInsertIterator * operator-> () + { + return this; + } + + /** + * Increment. + */ + FilterInsertIterator & operator++ () + { + return *this; + } + + /** + * Increment. + */ + FilterInsertIterator & operator++ (int) + { + return *this; + } + }; + + /** + * Convenience function: make a FilterInsertIterator. + */ + template <typename Iter_, typename Pred_> + FilterInsertIterator<Iter_, Pred_> filter_inserter( + const Iter_ & i, const Pred_ & p) + { + return FilterInsertIterator<Iter_, Pred_>(i, p); + } +} + +#endif diff --git a/paludis/filter_insert_iterator_TEST.cc b/paludis/filter_insert_iterator_TEST.cc new file mode 100644 index 000000000..8a173689f --- /dev/null +++ b/paludis/filter_insert_iterator_TEST.cc @@ -0,0 +1,60 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "filter_insert_iterator.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <set> + +using namespace test; +using namespace paludis; + +#ifndef DOXYGEN +struct Counter +{ + int n; + + Counter() : + n(0) + { + } + + int operator() () + { + return n++; + } +}; + +int is_even(const int & v) +{ + return ! (v & 1); +} +#endif + + +namespace test_cases +{ + struct FilterInsertIteratorTest : TestCase + { + FilterInsertIteratorTest() : TestCase("filter insert iterator") { } + + void run() + { + std::set<int> v; + std::generate_n(filter_inserter(std::inserter(v, v.begin()), std::ptr_fun(&is_even)), + 5, Counter()); + TEST_CHECK_EQUAL(v.size(), 3); + for (int n = 0 ; n < 5 ; ++n) + { + TestMessageSuffix s("n=" + stringify(n)); + if (is_even(n)) + { + TEST_CHECK(v.end() != v.find(n)); + TEST_CHECK_EQUAL(*v.find(n), n); + } + else + TEST_CHECK(v.end() == v.find(n)); + } + } + } test_filter_insert_iterator; +} + diff --git a/paludis/fs_entry.cc b/paludis/fs_entry.cc new file mode 100644 index 000000000..f6e49e902 --- /dev/null +++ b/paludis/fs_entry.cc @@ -0,0 +1,178 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "fs_entry.hh" +#include "fs_error.hh" +#include "exception.hh" +#include "internal_error.hh" +#include "stringify.hh" + +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> + +/** \file + * Implementation of paludis::FSEntry. + * + * \ingroup Filesystem + */ + +using namespace paludis; + +FSEntry::FSEntry(const std::string & path) : + ComparisonPolicyType(&FSEntry::_path), + _path(path) +{ + _normalise(); +} + +FSEntry::FSEntry(const FSEntry & other) : + ComparisonPolicyType(&FSEntry::_path), + _path(other._path) +{ +} + +FSEntry::~FSEntry() +{ +} + +const FSEntry & +FSEntry::operator= (const FSEntry & other) +{ + _path = other._path; + return *this; +} + +FSEntry::operator std::string() const +{ + return _path; +} + +FSEntry +FSEntry::operator/ (const FSEntry & rhs) const +{ + return FSEntry(_path + "/" + rhs._path); +} + +const FSEntry & +FSEntry::operator/= (const FSEntry & rhs) +{ + _path.append("/"); + _path.append(rhs._path); + _normalise(); + return *this; +} + +bool +FSEntry::exists() const +{ + struct stat s; + + if (0 != stat(_path.c_str(), &s)) + { + if (errno != ENOENT) + throw FSError("Error checking whether '" + stringify(_path) + "' exists: " + + strerror(errno)); + return false; + } + + return true; +} + +bool +FSEntry::is_directory() const +{ + struct stat s; + + if (0 != stat(_path.c_str(), &s)) + { + if (errno != ENOENT) + throw FSError("Error checking whether '" + stringify(_path) + "' is a directory: " + + strerror(errno)); + return false; + } + + return S_ISDIR(s.st_mode); +} + +bool +FSEntry::is_regular_file() const +{ + struct stat s; + + if (0 != stat(_path.c_str(), &s)) + { + if (errno != ENOENT) + throw FSError("Error checking whether '" + stringify(_path) + "' is a regular file: " + + strerror(errno)); + return false; + } + + return S_ISREG(s.st_mode); +} + +void +FSEntry::_normalise() +{ + try + { + std::string new_path; + std::string::size_type p(0); + while (p < _path.length()) + { + if ('/' == _path[p]) + { + new_path += '/'; + while (++p < _path.length()) + if ('/' != _path[p]) + break; + } + else + new_path += _path[p++]; + } + _path = new_path; + + if (! _path.empty()) + if ('/' == _path.at(_path.length() - 1)) + _path.erase(_path.length() - 1); + if (_path.empty()) + _path = "/"; + } + catch (const std::exception & e) + { + Context c("When normalising FSEntry path '" + _path + "':"); + throw InternalError(__PRETTY_FUNCTION__, + "caught std::exception '" + stringify(e.what()) + "'"); + } +} + +std::string +FSEntry::basename() const +{ + return _path.substr(_path.rfind('/') + 1); +} + +std::ostream & +paludis::operator<< (std::ostream & s, const FSEntry & f) +{ + s << std::string(f); + return s; +} + + diff --git a/paludis/fs_entry.hh b/paludis/fs_entry.hh new file mode 100644 index 000000000..466fa944a --- /dev/null +++ b/paludis/fs_entry.hh @@ -0,0 +1,131 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_FS_ENTRY_HH +#define PALUDIS_GUARD_PALUDIS_FS_ENTRY_HH 1 + +#include <string> +#include <ostream> +#include <paludis/comparison_policy.hh> + +/** \file + * Declarations for paludis::Filesystem. + * + * \ingroup Filesystem + */ + +namespace paludis +{ + /** + * Represents an entry (which may or may not exist) in the filesystem. + * + * \ingroup Filesystem + */ + class FSEntry : public ComparisonPolicy< + FSEntry, + comparison_mode::FullComparisonTag, + comparison_method::CompareByMemberTag<std::string> > + { + private: + std::string _path; + + void _normalise(); + + public: + /** + * Constructor, from a path. + */ + FSEntry(const std::string & path); + + /** + * Copy constructor. + */ + FSEntry(const FSEntry & other); + + /** + * Destructor. + */ + ~FSEntry(); + + /** + * Assignment, from another FSEntry. + */ + const FSEntry & operator= (const FSEntry & other); + + /** + * Join with another FSEntry. + */ + FSEntry operator/ (const FSEntry & rhs) const; + + /** + * Append another FSEntry. + */ + const FSEntry & operator/= (const FSEntry & rhs); + + /** + * Join with another path. + */ + FSEntry operator/ (const std::string & rhs) const + { + return operator/ (FSEntry(rhs)); + } + + /** + * Append another path. + */ + const FSEntry & operator/= (const std::string & rhs) + { + return operator/= (FSEntry(rhs)); + } + + /** + * Fetch a string representation of our path. + */ + operator std::string() const; + + /** + * Does a filesystem entry exist at our location? + */ + bool exists() const; + + /** + * Does a filesystem entry exist at our location, and if it does, + * is it a directory? + */ + bool is_directory() const; + + /** + * Does a filesystem entry exist at our location, and if it does, + * is it a regular file? + */ + bool is_regular_file() const; + + /** + * Return the last part of our path (eg '/foo/bar' => 'bar'). + */ + std::string basename() const; + }; + + /** + * An FSEntry can be written to an ostream. + */ + std::ostream & operator<< (std::ostream & s, const FSEntry & f); +} + +#endif diff --git a/paludis/fs_entry_TEST.cc b/paludis/fs_entry_TEST.cc new file mode 100644 index 000000000..b2e1dd05a --- /dev/null +++ b/paludis/fs_entry_TEST.cc @@ -0,0 +1,61 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "fs_entry.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace paludis; +using namespace test; + +/** \file + * Test cases for fs_entry.hh. + * + * \todo this is nowhere near complete. + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Test FSEntry construction and manipulation. + */ + struct TestFSEntryManipulation : TestCase + { + TestFSEntryManipulation() : TestCase("construction and manipulation") { } + + void run() + { + FSEntry f("/foo/bar"); + FSEntry c(f); + TEST_CHECK_EQUAL(f, FSEntry("/foo/bar")); + TEST_CHECK_EQUAL(c, FSEntry("/foo/bar")); + f = FSEntry("/baz"); + TEST_CHECK_EQUAL(f, FSEntry("/baz")); + TEST_CHECK_EQUAL(c, FSEntry("/foo/bar")); + c /= "moo"; + TEST_CHECK_EQUAL(f, FSEntry("/baz")); + TEST_CHECK_EQUAL(c, FSEntry("/foo/bar/moo")); + f = c / f; + TEST_CHECK_EQUAL(f, FSEntry("/foo/bar/moo/baz")); + TEST_CHECK_EQUAL(c, FSEntry("/foo/bar/moo")); + } + } test_fs_entry_manipulation; +} diff --git a/paludis/fs_error.cc b/paludis/fs_error.cc new file mode 100644 index 000000000..429164aac --- /dev/null +++ b/paludis/fs_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "fs_error.hh" + +using namespace paludis; + +FSError::FSError(const std::string & message) throw () : + Exception(message) +{ +} + diff --git a/paludis/fs_error.hh b/paludis/fs_error.hh new file mode 100644 index 000000000..445da391a --- /dev/null +++ b/paludis/fs_error.hh @@ -0,0 +1,46 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_FS_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_FS_ERROR_HH 1 + +#include <paludis/exception.hh> + +/** \file + * Declarations for the FSError exception class. + */ + +namespace paludis +{ + /** + * Generic filesystem error class. + * + * \ingroup Exception + */ + class FSError : public Exception + { + public: + /** + * Constructor. + */ + FSError(const std::string & message) throw (); + }; +} + +#endif diff --git a/paludis/getenv.cc b/paludis/getenv.cc new file mode 100644 index 000000000..d459acbbc --- /dev/null +++ b/paludis/getenv.cc @@ -0,0 +1,27 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "getenv.hh" +#include <cstdlib> + +using namespace paludis; + +GetenvError::GetenvError(const std::string & key) throw () : + Exception("Environment variable '" + key + "' not set") +{ +} + +std::string +paludis::getenv_with_default(const std::string & key, const std::string & def) +{ + const char * const e(std::getenv(key.c_str())); + return e ? e : def; +} + +std::string +paludis::getenv_or_error(const std::string & key) +{ + const char * const e(std::getenv(key.c_str())); + if (! e) + throw GetenvError(key); + return e; +} diff --git a/paludis/getenv.hh b/paludis/getenv.hh new file mode 100644 index 000000000..b68d54ba1 --- /dev/null +++ b/paludis/getenv.hh @@ -0,0 +1,40 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_GETENV_HH +#define PALUDIS_GUARD_PALUDIS_GETENV_HH 1 + +#include <paludis/exception.hh> +#include <string> + +namespace paludis +{ + class GetenvError : public Exception + { + public: + GetenvError(const std::string & key) throw (); + }; + + std::string getenv_with_default(const std::string & key, const std::string & def); + + std::string getenv_or_error(const std::string & key); +} + +#endif diff --git a/paludis/getenv_TEST.cc b/paludis/getenv_TEST.cc new file mode 100644 index 000000000..e6990792a --- /dev/null +++ b/paludis/getenv_TEST.cc @@ -0,0 +1,34 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "getenv.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> + +using namespace test; +using namespace paludis; + +namespace test_cases +{ + struct GetenvWithDefaultTest : TestCase + { + GetenvWithDefaultTest() : TestCase("getenv_with_default") { } + + void run() + { + TEST_CHECK(! getenv_with_default("HOME", "!").empty()); + TEST_CHECK_EQUAL(getenv_with_default("HOME", "!").at(0), '/'); + TEST_CHECK_EQUAL(getenv_with_default("THEREISNOSUCHVARIABLE", "moo"), "moo"); + } + } test_getenv_with_default; + + struct GetenvOrErrorTest : TestCase + { + GetenvOrErrorTest() : TestCase("getenv_or_error") { } + + void run() + { + TEST_CHECK(! getenv_or_error("HOME").empty()); + TEST_CHECK_THROWS(getenv_or_error("THEREISNOSUCHVARIABLE"), GetenvError); + } + } test_getenv_or_error; +} diff --git a/paludis/indirect_iterator.cc b/paludis/indirect_iterator.cc new file mode 100644 index 000000000..cac202df2 --- /dev/null +++ b/paludis/indirect_iterator.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "indirect_iterator.hh" + diff --git a/paludis/indirect_iterator.hh b/paludis/indirect_iterator.hh new file mode 100644 index 000000000..a73b8cbe3 --- /dev/null +++ b/paludis/indirect_iterator.hh @@ -0,0 +1,159 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_INDIRECT_ITERATOR_HH +#define PALUDIS_GUARD_PALUDIS_INDIRECT_ITERATOR_HH 1 + +#include <iterator> +#include <paludis/instantiation_policy.hh> +#include <paludis/comparison_policy.hh> + +namespace paludis +{ + template <typename Iter_, typename Value_> + class IndirectIterator; + + namespace + { + /** + * Determine the comparison class to use for IndirectIterator. + */ + template <typename IterCategory_, typename Iter_, typename Value_> + struct Comparisons + { + /** + * Default to providing == and !=. + */ + typedef ComparisonPolicy<IndirectIterator<Iter_, Value_>, + comparison_mode::EqualityComparisonTag, + comparison_method::CompareByMemberTag<Iter_> > Type; + }; + + /** + * Determine the comparison class to use for IndirectIterator + * (specialisation for random access iterators). + */ + template <typename Iter_, typename Value_> + struct Comparisons<std::random_access_iterator_tag, Iter_, Value_> + { + /** + * Provide the full range of comparison operators. + */ + typedef ComparisonPolicy<IndirectIterator<Iter_, Value_>, + comparison_mode::FullComparisonTag, + comparison_method::CompareByMemberTag<Iter_> > Type; + }; + } + + /** + * An IndirectIterator is an iterator adapter that does one additional level + * of dereferencing. + */ + template <typename Iter_, typename Value_> + class IndirectIterator : public std::iterator<typename std::iterator_traits<Iter_>::iterator_category, Value_>, + public Comparisons<typename std::iterator_traits<Iter_>::iterator_category, + Iter_, Value_>::Type + { + private: + Iter_ _i; + + public: + /** + * Constructor, from a base iterator. + */ + IndirectIterator(const Iter_ & i) : + Comparisons<typename std::iterator_traits<Iter_>::iterator_category, Iter_, Value_>::Type( + &IndirectIterator<Iter_, Value_>::_i), + _i(i) + { + } + + /** + * Copy constructor. + */ + IndirectIterator(const IndirectIterator & other) : + Comparisons<typename std::iterator_traits<Iter_>::iterator_category, Iter_, Value_>::Type( + &IndirectIterator<Iter_, Value_>::_i), + _i(other._i) + { + } + + /** + * Assignment. + */ + const IndirectIterator & operator= (const IndirectIterator & other) + { + _i = other._i; + return *this; + } + + /** + * Dereference. + */ + Value_ & operator*() + { + return **_i; + } + + /** + * Dereference arrow. + */ + Value_ * operator->() + { + return &**_i; + } + + /** + * Dereference, const. + */ + const Value_ & operator*() const + { + return **_i; + } + + /** + * Dereference arrow, const. + */ + const Value_ * operator->() const + { + return &**_i; + } + + /** + * Increment. + */ + IndirectIterator & operator++ () + { + ++_i; + return *this; + } + + /** + * Increment. + */ + IndirectIterator operator++ (int) + { + IndirectIterator tmp(*this); + ++_i; + return tmp; + } + }; +} + +#endif diff --git a/paludis/indirect_iterator_TEST.cc b/paludis/indirect_iterator_TEST.cc new file mode 100644 index 000000000..121daec37 --- /dev/null +++ b/paludis/indirect_iterator_TEST.cc @@ -0,0 +1,146 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "indirect_iterator.hh" +#include "counted_ptr.hh" +#include "deleter.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <vector> +#include <list> +#include <algorithm> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for IndirectIterator. + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Test IndirectIterator over a vector of CountedPtr of int. + * + * \ingroup Test + */ + struct IndirectIteratorVecCPIntTest : TestCase + { + IndirectIteratorVecCPIntTest() : TestCase("vector<CountedPtr<int> >") { } + + void run() + { + std::vector<CountedPtr<int, count_policy::ExternalCountTag> > v; + v.push_back(CountedPtr<int, count_policy::ExternalCountTag>(new int(5))); + v.push_back(CountedPtr<int, count_policy::ExternalCountTag>(new int(10))); + IndirectIterator<std::vector<CountedPtr<int, + count_policy::ExternalCountTag> >::iterator, int> vi(v.begin()), vi_end(v.end()); + TEST_CHECK(vi != vi_end); + TEST_CHECK(vi < vi_end); + TEST_CHECK(! (vi > vi_end)); + TEST_CHECK_EQUAL(*vi, 5); + TEST_CHECK(++vi != vi_end); + TEST_CHECK(vi < vi_end); + TEST_CHECK(! (vi > vi_end)); + TEST_CHECK_EQUAL(*vi, 10); + TEST_CHECK(++vi == vi_end); + } + } test_indirect_iterator_vec_cp_int; + + /** + * \test Test IndirectIterator over a list of CountedPtr of int. + * + * \ingroup Test + */ + struct IndirectIteratorListCPIntTest : TestCase + { + IndirectIteratorListCPIntTest() : TestCase("list<CountedPtr<int> >") { } + + void run() + { + std::list<CountedPtr<int, count_policy::ExternalCountTag> > v; + v.push_back(CountedPtr<int, count_policy::ExternalCountTag>(new int(5))); + v.push_back(CountedPtr<int, count_policy::ExternalCountTag>(new int(10))); + IndirectIterator<std::list<CountedPtr<int, + count_policy::ExternalCountTag> >::iterator, int> vi(v.begin()), vi_end(v.end()); + TEST_CHECK(vi != vi_end); + TEST_CHECK_EQUAL(*vi, 5); + TEST_CHECK(++vi != vi_end); + TEST_CHECK_EQUAL(*vi, 10); + TEST_CHECK(++vi == vi_end); + } + } test_indirect_iterator_list_cp_int; + + /** + * \test Test IndirectIterator over a vector of int *. + * + * \ingroup Test + */ + struct IndirectIteratorVecPIntTest : TestCase + { + IndirectIteratorVecPIntTest() : TestCase("vector<int *>") { } + + void run() + { + std::vector<int *> v; + v.push_back(new int(5)); + v.push_back(new int(10)); + IndirectIterator<std::vector<int *>::iterator, int> vi(v.begin()), vi_end(v.end()); + TEST_CHECK(vi != vi_end); + TEST_CHECK(vi < vi_end); + TEST_CHECK(! (vi > vi_end)); + TEST_CHECK_EQUAL(*vi, 5); + TEST_CHECK(++vi != vi_end); + TEST_CHECK(vi < vi_end); + TEST_CHECK(! (vi > vi_end)); + TEST_CHECK_EQUAL(*vi, 10); + TEST_CHECK(++vi == vi_end); + + std::for_each(v.begin(), v.end(), Deleter()); + } + } test_indirect_iterator_vec_p_int; + + /** + * \test Test IndirectIterator over a list of int *. + * + * \ingroup Test + */ + struct IndirectIteratorListPIntTest : TestCase + { + IndirectIteratorListPIntTest() : TestCase("list<CountedPtr<int *>") { } + + void run() + { + std::list<int *> v; + v.push_back(new int(5)); + v.push_back(new int(10)); + IndirectIterator<std::list<int *>::iterator, int> vi(v.begin()), vi_end(v.end()); + TEST_CHECK(vi != vi_end); + TEST_CHECK_EQUAL(*vi, 5); + TEST_CHECK(++vi != vi_end); + TEST_CHECK_EQUAL(*vi, 10); + TEST_CHECK(++vi == vi_end); + + std::for_each(v.begin(), v.end(), Deleter()); + } + } test_indirect_iterator_list_p_int; +} + diff --git a/paludis/instantiation_policy.cc b/paludis/instantiation_policy.cc new file mode 100644 index 000000000..9e2c0da58 --- /dev/null +++ b/paludis/instantiation_policy.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "instantiation_policy.hh" + diff --git a/paludis/instantiation_policy.hh b/paludis/instantiation_policy.hh new file mode 100644 index 000000000..c4dbca984 --- /dev/null +++ b/paludis/instantiation_policy.hh @@ -0,0 +1,184 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_INSTANTIATION_POLICY_HH +#define PALUDIS_GUARD_PALUDIS_INSTANTIATION_POLICY_HH 1 + +namespace paludis +{ + /** + * Instantiation policies for paludis::InstantiationPolicy. + */ + namespace instantiation_method + { + /** + * Cannot be copied or assigned to. + */ + struct NonCopyableTag + { + }; + + /** + * Cannot be instantiated. + */ + struct NonInstantiableTag + { + }; + + /** + * Single instance created at startup. + */ + struct SingletonAtStartupTag + { + }; + + /** + * Single instance created when needed. + */ + struct SingletonAsNeededTag + { + }; + } + +#ifdef DOXYGEN + /** + * InstantiationPolicy is used to specify behaviour of classes that have + * something other than the default C++ instantiation behaviour. + */ + template <typename OurType_, typename InstantiationMethodTag_> + struct InstantiationPolicy + { + }; +#else + template <typename OurType_, typename InstantiationMethodTag_> + struct InstantiationPolicy; +#endif + + /** + * InstantiationPolicy: specialisation for classes that cannot be copied + * or assigned to. + */ + template<typename OurType_> + class InstantiationPolicy<OurType_, instantiation_method::NonCopyableTag> + { + private: + InstantiationPolicy(const InstantiationPolicy &); + + const InstantiationPolicy & operator= (const InstantiationPolicy &); + + protected: + ~InstantiationPolicy() + { + } + + InstantiationPolicy() + { + } + }; + + /** + * InstantiationPolicy: specialisation for classes that cannot be created. + */ + template<typename OurType_> + class InstantiationPolicy<OurType_, instantiation_method::NonInstantiableTag> + { + private: + InstantiationPolicy(); + + InstantiationPolicy(const InstantiationPolicy &); + + const InstantiationPolicy & operator= (const InstantiationPolicy &); + + protected: + ~InstantiationPolicy() + { + } + }; +} + +#include <paludis/counted_ptr.hh> + +namespace paludis +{ + /** + * InstantiationPolicy: specialisation for singleton classes that are + * created at startup. + */ + template<typename OurType_> + class InstantiationPolicy<OurType_, instantiation_method::SingletonAtStartupTag> + { + private: + InstantiationPolicy(const InstantiationPolicy &); + + const InstantiationPolicy & operator= (const InstantiationPolicy &); + + static CountedPtr<OurType_, count_policy::ExternalCountTag> _instance; + + protected: + InstantiationPolicy() + { + } + + public: + /** + * Fetch our instance. + */ + static OurType_ * get_instance() + { + return _instance.raw_pointer(); + } + }; + + template <typename OurType_> + CountedPtr<OurType_, count_policy::ExternalCountTag> + InstantiationPolicy<OurType_, instantiation_method::SingletonAtStartupTag>::_instance( + new OurType_); + + /** + * InstantiationPolicy: specialisation for singleton classes that are + * created as needed. + */ + template<typename OurType_> + class InstantiationPolicy<OurType_, instantiation_method::SingletonAsNeededTag> + { + private: + InstantiationPolicy(const InstantiationPolicy &); + + const InstantiationPolicy & operator= (const InstantiationPolicy &); + + static OurType_ * _instance; + + protected: + InstantiationPolicy() + { + } + + public: + /** + * Fetch our instance. + */ + static OurType_ * get_instance() + { + static OurType_ instance; + return &instance; + } + }; +} + +#endif diff --git a/paludis/instantiation_policy_TEST.cc b/paludis/instantiation_policy_TEST.cc new file mode 100644 index 000000000..d47ff513d --- /dev/null +++ b/paludis/instantiation_policy_TEST.cc @@ -0,0 +1,127 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "instantiation_policy.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <string> + +using namespace test; +using namespace paludis; + +/** + * \file + * Test cases for instantiation_policy.hh . + */ + +#ifndef DOXYGEN + +class MyClass : + public InstantiationPolicy<MyClass, instantiation_method::SingletonAsNeededTag> +{ + friend class InstantiationPolicy<MyClass, instantiation_method::SingletonAsNeededTag>; + + private: + MyClass() + { + ++instances; + } + + public: + std::string s; + + static int instances; +}; + +int MyClass::instances = 0; + +struct MyLoadAtStartupClass : + public InstantiationPolicy<MyLoadAtStartupClass, instantiation_method::SingletonAtStartupTag> +{ + friend class InstantiationPolicy<MyLoadAtStartupClass, instantiation_method::SingletonAtStartupTag>; + + private: + MyLoadAtStartupClass() + { + ++instances; + } + + public: + std::string s; + + static int instances; +}; + +int MyLoadAtStartupClass::instances = 0; + +#endif + +namespace test_cases +{ + /** + * \test Test singleton behaviour. + */ + struct SingletonPatternTest : TestCase + { + SingletonPatternTest() : TestCase("singleton test") { } + + bool repeatable() const + { + return false; + } + + void run() + { + TEST_CHECK_EQUAL(MyClass::instances, 0); + TEST_CHECK(0 != MyClass::get_instance()); + TEST_CHECK_EQUAL(MyClass::instances, 1); + TEST_CHECK_EQUAL(MyClass::get_instance(), MyClass::get_instance()); + TEST_CHECK(MyClass::get_instance()->s.empty()); + MyClass::get_instance()->s = "foo"; + TEST_CHECK_EQUAL(MyClass::get_instance()->s, "foo"); + } + } test_singleton_pattern; + + /** + * \test Test singleton create at startup behaviour. + */ + struct SingletonPatternCreateAtStartupTest : TestCase + { + SingletonPatternCreateAtStartupTest() : TestCase("singleton create at startup test") { } + + bool repeatable() const + { + return false; + } + + void run() + { + TEST_CHECK_EQUAL(MyLoadAtStartupClass::instances, 1); + TEST_CHECK(0 != MyLoadAtStartupClass::get_instance()); + TEST_CHECK_EQUAL(MyLoadAtStartupClass::instances, 1); + TEST_CHECK_EQUAL(MyLoadAtStartupClass::get_instance(), MyLoadAtStartupClass::get_instance()); + TEST_CHECK(MyLoadAtStartupClass::get_instance()->s.empty()); + MyLoadAtStartupClass::get_instance()->s = "foo"; + TEST_CHECK_EQUAL(MyLoadAtStartupClass::get_instance()->s, "foo"); + } + } test_singleton_pattern_create_at_startup; +} + + + diff --git a/paludis/internal_error.cc b/paludis/internal_error.cc new file mode 100644 index 000000000..03fbff1ff --- /dev/null +++ b/paludis/internal_error.cc @@ -0,0 +1,33 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "internal_error.hh" + +using namespace paludis; + +InternalError::InternalError(const char * const function, const std::string & message) throw () : + Exception("Eek! Internal error at " + std::string(function) + ": " + message) +{ +} + +InternalError::InternalError(const char * const function) throw () : + Exception("Eek! Internal error at " + std::string(function)) +{ +} + diff --git a/paludis/internal_error.hh b/paludis/internal_error.hh new file mode 100644 index 000000000..9cb0a1108 --- /dev/null +++ b/paludis/internal_error.hh @@ -0,0 +1,61 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_INTERNAL_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_INTERNAL_ERROR_HH 1 + +#include <paludis/exception.hh> + +/** \file + * Declaration for the InternalError exception class. + */ + +namespace paludis +{ + /** + * An InternalError is an Exception that is thrown if something that is + * never supposed to happen happens. + */ + class InternalError : public Exception + { + public: + /** + * Constructor. + * + * \param function Should be set to the __PRETTY_FUNCTION__ magic + * constant. + * + * \param message A short message. + */ + InternalError(const char * const function, const std::string & message) throw (); + + /** + * Constructor, with no message (deprecated). + * + * \param function Should be set to the __PRETTY_FUNCTION__ magic + * constant. + * + * \deprecated Use paludis::InternalError::InternalError(const char * const, + * const std::string &) instead. + */ + InternalError(const char * const function) throw () PALUDIS_ATTRIBUTE((deprecated)); + }; +} + +#endif diff --git a/paludis/is_const.cc b/paludis/is_const.cc new file mode 100644 index 000000000..ddfee6076 --- /dev/null +++ b/paludis/is_const.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "is_const.hh" + diff --git a/paludis/is_const.hh b/paludis/is_const.hh new file mode 100644 index 000000000..67e6d8fc7 --- /dev/null +++ b/paludis/is_const.hh @@ -0,0 +1,60 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_IS_CONST_HH +#define PALUDIS_GUARD_PALUDIS_IS_CONST_HH 1 + +/** \file + * Declarations for the IsConst class. + */ + +namespace paludis +{ + /** + * The value member will be true if a type is const and false otherwise. + */ + template <typename T_> + struct IsConst + { + /// Are we const? + static const bool value = false; + }; + + /** + * IsConst: specialisation for const. + */ + template <typename T_> + struct IsConst<const T_> + { + /// Are we const? + static const bool value = true; + }; + + /** + * IsConst: specialisation for const references. + */ + template <typename T_> + struct IsConst<const T_ &> + { + /// Are we const? + static const bool value = true; + }; +} + +#endif diff --git a/paludis/is_const_TEST.cc b/paludis/is_const_TEST.cc new file mode 100644 index 000000000..da4a8cd5a --- /dev/null +++ b/paludis/is_const_TEST.cc @@ -0,0 +1,58 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "is_const.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <string> + +using namespace test; +using namespace paludis; + +/** + * \file + * Test cases for is_const.hh . + */ + +namespace test_cases +{ + /** + * \test Test IsConst. + */ + struct IsConstTest : TestCase + { + IsConstTest() : TestCase("is const") { } + + void run() + { + TEST_CHECK(IsConst<const int>::value); + TEST_CHECK(IsConst<const std::string>::value); + TEST_CHECK(IsConst<const std::string &>::value); + TEST_CHECK(IsConst<int * const>::value); + + TEST_CHECK(! IsConst<int>::value); + TEST_CHECK(! IsConst<std::string>::value); + TEST_CHECK(! IsConst<std::string &>::value); + TEST_CHECK(! IsConst<const int *>::value); + } + } test_is_const; +} + + + diff --git a/paludis/is_file_with_extension.cc b/paludis/is_file_with_extension.cc new file mode 100644 index 000000000..4182cb211 --- /dev/null +++ b/paludis/is_file_with_extension.cc @@ -0,0 +1,20 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "is_file_with_extension.hh" + +using namespace paludis; + +bool +IsFileWithExtension::operator() (const FSEntry & f) const +{ + const std::string filename(f.basename()); + + if (filename.length() < _ext.length() + _prefix.length()) + return false; + if (0 != filename.compare(filename.length() - _ext.length(), + _ext.length(), _ext)) + return false; + if (0 != filename.compare(0, _prefix.length(), _prefix)) + return false; + return f.is_regular_file(); +} diff --git a/paludis/is_file_with_extension.hh b/paludis/is_file_with_extension.hh new file mode 100644 index 000000000..659a5e80e --- /dev/null +++ b/paludis/is_file_with_extension.hh @@ -0,0 +1,54 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_IS_FILE_WITH_EXTENSION_HH +#define PALUDIS_GUARD_PALUDIS_IS_FILE_WITH_EXTENSION_HH 1 + +#include <paludis/fs_entry.hh> +#include <string> +#include <functional> + +namespace paludis +{ + class IsFileWithExtension : + public std::unary_function<bool, FSEntry> + { + private: + const std::string _prefix; + const std::string _ext; + + public: + IsFileWithExtension(const std::string & ext) : + _prefix(""), + _ext(ext) + { + } + + IsFileWithExtension(const std::string & prefix, const std::string & ext) : + _prefix(prefix), + _ext(ext) + { + } + + bool operator() (const FSEntry & f) const; + }; +} + +#endif diff --git a/paludis/is_file_with_extension_TEST.cc b/paludis/is_file_with_extension_TEST.cc new file mode 100644 index 000000000..49560c8e3 --- /dev/null +++ b/paludis/is_file_with_extension_TEST.cc @@ -0,0 +1,24 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "is_file_with_extension.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <vector> +#include <algorithm> + +using namespace paludis; +using namespace test; + +namespace test_cases +{ + struct IsFileWithExtensionTest : TestCase + { + IsFileWithExtensionTest() : TestCase("is file with extension") { } + + void run() + { + /// \todo + } + } test_is_file_with_extension; +} + diff --git a/paludis/join.cc b/paludis/join.cc new file mode 100644 index 000000000..ea1844df4 --- /dev/null +++ b/paludis/join.cc @@ -0,0 +1,21 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "join.hh" + diff --git a/paludis/join.hh b/paludis/join.hh new file mode 100644 index 000000000..523018330 --- /dev/null +++ b/paludis/join.hh @@ -0,0 +1,57 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_JOIN_HH +#define PALUDIS_GUARD_PALUDIS_JOIN_HH 1 + +#include <string> +#include <paludis/stringify.hh> + +namespace paludis +{ + /** + * Join together the items from i to end using joiner. + */ + template <typename I_, typename T_> + T_ join(I_ i, I_ end, const T_ & joiner) + { + T_ result; + if (i != end) + while (true) + { + result += stringify(*i); + if (++i == end) + break; + result += joiner; + } + return result; + } + + /** + * Convenience alternative join allowing a char * to be used for a + * string. + */ + template <typename I_> + std::string join(I_ begin, const I_ end, const char * const t) + { + return join(begin, end, std::string(t)); + } +} + +#endif diff --git a/paludis/join_TEST.cc b/paludis/join_TEST.cc new file mode 100644 index 000000000..9badb1e08 --- /dev/null +++ b/paludis/join_TEST.cc @@ -0,0 +1,101 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "join.hh" +#include <test/test_runner.hh> +#include <test/test_framework.hh> +#include <vector> +#include <list> + +using namespace paludis; +using namespace test; + +/** \file + * Test cases for join.hh . + * + * \ingroup Test + */ + +namespace test_cases +{ + /** + * \test Test join on a vector. + * + * \ingroup Test + */ + struct JoinVectorTest : TestCase + { + JoinVectorTest() : TestCase("join vector") { } + + void run() + { + std::vector<std::string> v; + v.push_back("one"); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "/"), "one"); + v.push_back("two"); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "/"), "one/two"); + v.push_back("three"); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "/"), "one/two/three"); + } + } test_join_vector; + + /** + * \test Test join on a list. + * + * \ingroup Test + */ + struct JoinListTest : TestCase + { + JoinListTest() : TestCase("join list") { } + + void run() + { + std::list<std::string> v; + v.push_back("one"); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "/"), "one"); + v.push_back("two"); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "/"), "one/two"); + v.push_back("three"); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "/"), "one/two/three"); + } + } test_join_list; + + /** + * \test Test join with empty things. + * + * \ingroup Test + */ + struct JoinEmptyTest : TestCase + { + JoinEmptyTest() : TestCase("join empty") { } + + void run() + { + std::list<std::string> v; + TEST_CHECK_EQUAL(join(v.begin(), v.end(), ""), ""); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "*"), ""); + v.push_back(""); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), ""), ""); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "*"), ""); + v.push_back(""); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), ""), ""); + TEST_CHECK_EQUAL(join(v.begin(), v.end(), "*"), "*"); + } + } test_join_empty; +} diff --git a/paludis/key_value_config_file.cc b/paludis/key_value_config_file.cc new file mode 100644 index 000000000..221747f93 --- /dev/null +++ b/paludis/key_value_config_file.cc @@ -0,0 +1,26 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "key_value_config_file.hh" + +using namespace paludis; + +KeyValueConfigFile::KeyValueConfigFile(std::istream * const s) : + ConfigFile(s) +{ + need_lines(); +} + +void +KeyValueConfigFile::accept_line(const std::string & line) const +{ + std::string::size_type p(line.find('=')); + if (std::string::npos == p) + _entries[line] = ""; + else + { + std::string key(line.substr(0, p)), value(line.substr(p + 1)); + normalise_line(key); + normalise_line(value); + _entries[key] = value; + } +} diff --git a/paludis/key_value_config_file.hh b/paludis/key_value_config_file.hh new file mode 100644 index 000000000..cf5aa845f --- /dev/null +++ b/paludis/key_value_config_file.hh @@ -0,0 +1,55 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#ifndef PALUDIS_GUARD_PALUDIS_KEY_VALUE_CONFIG_FILE_HH +#define PALUDIS_GUARD_PALUDIS_KEY_VALUE_CONFIG_FILE_HH 1 + +#include <paludis/config_file.hh> +#include <map> + +/** \file + * Declarations for the KeyValueConfigFile class. + * + * \ingroup ConfigFile + */ + + +namespace paludis +{ + /** + * A KeyValueConfigFile is a ConfigFile that provides access to the + * normalised lines. Do not subclass. + * + * \ingroup ConfigFile + */ + class KeyValueConfigFile : protected ConfigFile + { + private: + mutable std::map<std::string, std::string> _entries; + + protected: + void accept_line(const std::string &) const; + + public: + KeyValueConfigFile(std::istream * const); + + typedef std::map<std::string, std::string>::const_iterator Iterator; + + Iterator begin() const + { + return _entries.begin(); + } + + Iterator end() const + { + return _entries.end(); + } + + std::string get(const std::string & key) + { + return _entries[key]; + } + }; + +} + +#endif diff --git a/paludis/key_value_config_file_TEST.cc b/paludis/key_value_config_file_TEST.cc new file mode 100644 index 000000000..4c25b3d9a --- /dev/null +++ b/paludis/key_value_config_file_TEST.cc @@ -0,0 +1,24 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "key_value_config_file.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <vector> +#include <algorithm> + +using namespace paludis; +using namespace test; + +namespace test_cases +{ + struct KeyValueConfigFileTest : TestCase + { + KeyValueConfigFileTest() : TestCase("key value config file") { } + + void run() + { + /// \todo + } + } test_key_value_config_file; +} + diff --git a/paludis/keyword_name.cc b/paludis/keyword_name.cc new file mode 100644 index 000000000..da91aa331 --- /dev/null +++ b/paludis/keyword_name.cc @@ -0,0 +1,22 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "keyword_name.hh" + diff --git a/paludis/keyword_name.hh b/paludis/keyword_name.hh new file mode 100644 index 000000000..156b02842 --- /dev/null +++ b/paludis/keyword_name.hh @@ -0,0 +1,43 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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_KEYWORD_NAME_HH +#define PALUDIS_GUARD_PALUDIS_KEYWORD_NAME_HH 1 + +#include <paludis/validated.hh> +#include <paludis/keyword_name_validator.hh> +#include <string> + +/** \file + * Declarations for the KeywordName class. + * + * \ingroup Environment + */ +namespace paludis +{ + /** + * A KeywordName holds a std::string that is a valid name for a KEYWORD. + * + * \ingroup Database + */ + typedef Validated<std::string, KeywordNameValidator> KeywordName; + +} + +#endif diff --git a/paludis/keyword_name_error.cc b/paludis/keyword_name_error.cc new file mode 100644 index 000000000..b9fdce496 --- /dev/null +++ b/paludis/keyword_name_error.cc @@ -0,0 +1,29 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "keyword_name_error.hh" + +using namespace paludis; + +KeywordNameError::KeywordNameError(const std::string & name) throw () : + NameError(name, "keyword name") +{ +} + diff --git a/paludis/keyword_name_error.hh b/paludis/keyword_name_error.hh new file mode 100644 index 000000000..40ed70830 --- /dev/null +++ b/paludis/keyword_name_error.hh @@ -0,0 +1,54 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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_KEYWORD_NAME_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_KEYWORD_NAME_ERROR_HH 1 + +#include <paludis/name_error.hh> +#include <string> + +/** \file + * Declarations for KeywordNameError. + * + * \ingroup Environment + * \ingroup Exception + */ + +namespace paludis +{ + /** + * A KeywordNameError is thrown if an invalid value is assigned to + * a KeywordNameName. + * + * \ingroup Environment + * \ingroup Exception + */ + class KeywordNameError : public NameError + { + public: + /** + * Constructor. + */ + KeywordNameError(const std::string & name) throw (); + }; +} + + + +#endif diff --git a/paludis/keyword_name_validator.cc b/paludis/keyword_name_validator.cc new file mode 100644 index 000000000..e65632cc7 --- /dev/null +++ b/paludis/keyword_name_validator.cc @@ -0,0 +1,63 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 "keyword_name_validator.hh" +#include "keyword_name_error.hh" + +using namespace paludis; + +void +KeywordNameValidator::validate(const std::string & s) +{ + static const std::string allowed_chars( + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789-+_"); + + do + { + switch (s.length()) + { + case 0: + continue; + + case 1: + if ("*" == s) + return; + continue; + + case 2: + if ("-*" == s) + return; + + /* fall throuth */ + default: + if (std::string::npos != s.find_first_not_of(allowed_chars, + ('~' == s.at(0) ? 1 : 0))) + continue; + } + + return; + + } while (false); + + Context c("When validating keyword name '" + s + "':"); + throw KeywordNameError(s); +} + diff --git a/paludis/keyword_name_validator.hh b/paludis/keyword_name_validator.hh new file mode 100644 index 000000000..b956aa8ff --- /dev/null +++ b/paludis/keyword_name_validator.hh @@ -0,0 +1,51 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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_KEYWORD_NAME_VALIDATOR_HH +#define PALUDIS_GUARD_PALUDIS_KEYWORD_NAME_VALIDATOR_HH 1 + +#include <paludis/instantiation_policy.hh> +#include <string> + +/** \file + * Declarations for the KeywordNameValidator class. + * + * \ingroup Environment + */ + +namespace paludis +{ + /** + * A KeywordNameValidator handles validation rules for the value of a + * UseFlagName. + * + * \ingroup Environment + */ + struct KeywordNameValidator : + private InstantiationPolicy<KeywordNameValidator, instantiation_method::NonInstantiableTag> + { + /** + * If the parameter is not a valid value for a KeywordName, + * throw a KeywordNameError. + */ + static void validate(const std::string &); + }; +} + +#endif diff --git a/paludis/line_config_file.cc b/paludis/line_config_file.cc new file mode 100644 index 000000000..46f760b70 --- /dev/null +++ b/paludis/line_config_file.cc @@ -0,0 +1,36 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "line_config_file.hh" + +using namespace paludis; + +LineConfigFile::LineConfigFile(std::istream * const s) : + ConfigFile(s) +{ + need_lines(); +} + +void +LineConfigFile::accept_line(const std::string & s) const +{ + _lines.push_back(s); +} + diff --git a/paludis/line_config_file.hh b/paludis/line_config_file.hh new file mode 100644 index 000000000..8f6b9ac50 --- /dev/null +++ b/paludis/line_config_file.hh @@ -0,0 +1,66 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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_LINE_CONFIG_FILE_HH +#define PALUDIS_GUARD_PALUDIS_LINE_CONFIG_FILE_HH 1 + +#include <paludis/config_file.hh> +#include <list> + +/** \file + * Declarations for the LineConfigFile class. + * + * \ingroup ConfigFile + */ + +namespace paludis +{ + /** + * A LineConfigFile is a ConfigFile that provides access to the + * normalised lines. Do not subclass. + * + * \ingroup ConfigFile + */ + class LineConfigFile : protected ConfigFile + { + private: + mutable std::list<std::string> _lines; + + protected: + void accept_line(const std::string &) const; + + public: + LineConfigFile(std::istream * const); + + typedef std::list<std::string>::const_iterator Iterator; + + Iterator begin() const + { + return _lines.begin(); + } + + Iterator end() const + { + return _lines.end(); + } + }; +} + +#endif diff --git a/paludis/line_config_file_TEST.cc b/paludis/line_config_file_TEST.cc new file mode 100644 index 000000000..3020f83b6 --- /dev/null +++ b/paludis/line_config_file_TEST.cc @@ -0,0 +1,75 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2006 Ciaran McCreesh <ciaranm@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 as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * 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 "line_config_file.hh" +#include <test/test_framework.hh> +#include <test/test_runner.hh> +#include <sstream> +#include <vector> +#include <iterator> + +using namespace test; +using namespace paludis; + +/** \file + * Test cases for line_config_file.hh . + * + * \ingroup Test + * \ingroup ConfigFile + */ + +namespace test_cases +{ + /** + * \test Test LineConfigFile. + * + * \ingroup Test + */ + struct LineConfigFileTest : TestCase + { + LineConfigFileTest() : TestCase("line config file") { } + + void run() + { + std::stringstream s; + s << "one" << std::endl; + s << " two \t " << std::endl; + s << " \t " << std::endl; + s << "" << std::endl; + s << "three" << std::endl; + s << "# blah" << std::endl; + s << " # blah" << std::endl; + s << "#" << std::endl; + s << " # \t " << std::endl; + s << "four four" << std::endl; + LineConfigFile ff(&s); + std::vector<std::string> f; + std::copy(ff.begin(), ff.end(), std::back_inserter(f)); + + TEST_CHECK_EQUAL(f.size(), 4); + TEST_CHECK_EQUAL(f.at(0), "one"); + TEST_CHECK_EQUAL(f.at(1), "two"); + TEST_CHECK_EQUAL(f.at(2), "three"); + TEST_CHECK_EQUAL(f.at(3), "four four"); + } + } test_line_config_file; +} + + diff --git a/paludis/mask_reasons.cc b/paludis/mask_reasons.cc new file mode 100644 index 000000000..503c31152 --- /dev/null +++ b/paludis/mask_reasons.cc @@ -0,0 +1,4 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include "mask_reasons.hh" + diff --git a/paludis/mask_reasons.hh b/paludis/mask_reasons.hh new file mode 100644 index 000000000..2b3459a09 --- /dev/null +++ b/paludis/mask_reasons.hh @@ -0,0 +1,30 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#ifndef PALUDIS_GUARD_PALUDIS_MASK_REASONS_HH +#define PALUDIS_GUARD_PALUDIS_MASK_REASONS_HH 1 + +#include <bitset> + +namespace paludis +{ + /** + * Each value represents one reason for a package being + * masked. + */ + enum MaskReason + { + mr_keyword, ///< no keyword match + mr_user_mask, ///< user package.mask + mr_profile_mask, ///< profile package.mask + mr_repository_mask, ///< repository package.mask + mr_eapi, ///< unknown eapi + last_mr ///< number of entries + }; + + /** + * A collection of reasons for why a package is masked. + */ + typedef std::bitset<last_mr> MaskReasons; +} + +#endif diff --git a/paludis/name_error.cc b/paludis/name_error.cc new file mode 100644 index 000000000..ff9ffe89e --- /dev/null +++ b/paludis/name_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "name_error.hh" + +using namespace paludis; + +NameError::NameError(const std::string & name, const std::string & role) throw () : + Exception("Name '" + name + "' is not a valid " + role) +{ +} + diff --git a/paludis/name_error.hh b/paludis/name_error.hh new file mode 100644 index 000000000..19c75fe5a --- /dev/null +++ b/paludis/name_error.hh @@ -0,0 +1,54 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_NAME_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_NAME_ERROR_HH 1 + +#include <paludis/exception.hh> + +/** \file + * Declaration for the NameError exception class. + * + * \ingroup Database + * \ingroup Exception + */ + +namespace paludis +{ + /** + * A NameError is an Exception that is thrown when some kind of invalid + * name is encountered. + * + * \ingroup Database + * \ingroup Exception + */ + class NameError : public Exception + { + protected: + /** + * Constructor. + * + * \param name The invalid name encountered. + * \param role The role for the name, for example "package name". + */ + NameError(const std::string & name, const std::string & role) throw (); + }; +} + +#endif diff --git a/paludis/no_resolvable_option_error.cc b/paludis/no_resolvable_option_error.cc new file mode 100644 index 000000000..34fd7cba0 --- /dev/null +++ b/paludis/no_resolvable_option_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "no_resolvable_option_error.hh" + +using namespace paludis; + +NoResolvableOptionError::NoResolvableOptionError() throw () : + DepListError("No resolvable || ( ) option") +{ +} + diff --git a/paludis/no_resolvable_option_error.hh b/paludis/no_resolvable_option_error.hh new file mode 100644 index 000000000..3f0f4f198 --- /dev/null +++ b/paludis/no_resolvable_option_error.hh @@ -0,0 +1,40 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_NO_RESOLVABLE_OPTION_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_NO_RESOLVABLE_OPTION_ERROR_HH 1 + +#include <paludis/dep_list_error.hh> + +namespace paludis +{ + /** + * Thrown if no entry in a || ( ) block is resolvable. + */ + class NoResolvableOptionError : public DepListError + { + public: + /** + * Constructor. + */ + NoResolvableOptionError() throw (); + }; +} + +#endif diff --git a/paludis/no_such_package_error.cc b/paludis/no_such_package_error.cc new file mode 100644 index 000000000..b43cd0c11 --- /dev/null +++ b/paludis/no_such_package_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "no_such_package_error.hh" + +using namespace paludis; + +NoSuchPackageError::NoSuchPackageError(const std::string & name) throw () : + PackageDatabaseLookupError("Could not find '" + name + "'") +{ +} + diff --git a/paludis/no_such_package_error.hh b/paludis/no_such_package_error.hh new file mode 100644 index 000000000..ca9d26e4e --- /dev/null +++ b/paludis/no_such_package_error.hh @@ -0,0 +1,45 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_NO_SUCH_PACKAGE_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_NO_SUCH_PACKAGE_ERROR_HH 1 + +#include <paludis/package_database_lookup_error.hh> + +/** \file + * Declaration for the NoSuchPackageError exception class. + */ + +namespace paludis +{ + /** + * Thrown if there is no Package in a PackageDatabase with the given + * name. + */ + class NoSuchPackageError : public PackageDatabaseLookupError + { + public: + /** + * Constructor. + */ + NoSuchPackageError(const std::string & name) throw (); + }; +} + +#endif diff --git a/paludis/no_such_repository_error.cc b/paludis/no_such_repository_error.cc new file mode 100644 index 000000000..a3cf719bf --- /dev/null +++ b/paludis/no_such_repository_error.cc @@ -0,0 +1,28 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "no_such_repository_error.hh" + +using namespace paludis; + +NoSuchRepositoryError::NoSuchRepositoryError(const std::string & name) throw () : + PackageDatabaseLookupError("Could not find repository '" + name + "'") +{ +} + diff --git a/paludis/no_such_repository_error.hh b/paludis/no_such_repository_error.hh new file mode 100644 index 000000000..acd32562b --- /dev/null +++ b/paludis/no_such_repository_error.hh @@ -0,0 +1,45 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_NO_SUCH_REPOSITORY_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_NO_SUCH_REPOSITORY_ERROR_HH 1 + +#include <paludis/package_database_lookup_error.hh> + +/** \file + * Declaration for the NoSuchRepositoryError exception class. + */ + +namespace paludis +{ + /** + * Thrown if there is no Repository in a RepositoryDatabase with the given + * name. + */ + class NoSuchRepositoryError : public PackageDatabaseLookupError + { + public: + /** + * Constructor. + */ + NoSuchRepositoryError(const std::string & name) throw (); + }; +} + +#endif diff --git a/paludis/no_such_version_error.cc b/paludis/no_such_version_error.cc new file mode 100644 index 000000000..bb81d7526 --- /dev/null +++ b/paludis/no_such_version_error.cc @@ -0,0 +1,30 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "no_such_version_error.hh" +#include "stringify.hh" + +using namespace paludis; + +NoSuchVersionError::NoSuchVersionError(const std::string & name, + const VersionSpec & version) throw () : + PackageDatabaseLookupError("No version of '" + name + "' named '" + stringify(version) + "'") +{ +} + diff --git a/paludis/no_such_version_error.hh b/paludis/no_such_version_error.hh new file mode 100644 index 000000000..7b99b1666 --- /dev/null +++ b/paludis/no_such_version_error.hh @@ -0,0 +1,47 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_NO_SUCH_VERSION_ERROR_HH +#define PALUDIS_GUARD_PALUDIS_NO_SUCH_VERSION_ERROR_HH 1 + +#include <paludis/package_database_lookup_error.hh> +#include <paludis/version_spec.hh> + +/** \file + * Declaration for the NoSuchVersionError exception class. + */ + +namespace paludis +{ + /** + * Thrown if there is no Version in a PackageDatabase with the given + * name. + */ + class NoSuchVersionError : public PackageDatabaseLookupError + { + public: + /** + * Constructor. + */ + NoSuchVersionError(const std::string & pkg_name, + const VersionSpec & version) throw (); + }; +} + +#endif diff --git a/paludis/package_database.cc b/paludis/package_database.cc new file mode 100644 index 000000000..acd876b84 --- /dev/null +++ b/paludis/package_database.cc @@ -0,0 +1,207 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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 "package_database.hh" +#include "no_such_package_error.hh" +#include "no_such_repository_error.hh" +#include "no_such_version_error.hh" +#include "internal_error.hh" +#include "duplicate_repository_error.hh" +#include "ambiguous_package_name_error.hh" +#include "package_dep_atom.hh" +#include "indirect_iterator.hh" +#include "stringify.hh" + +#include <list> +#include <map> +#include <set> + +using namespace paludis; + +namespace paludis +{ + /** + * Implementation data for a PackageDatabase. + */ + template<> + struct Implementation<PackageDatabase> : + InternalCounted<Implementation<PackageDatabase> > + { + /** + * Our Repository instances. + */ + std::list<Repository::ConstPointer> repositories; + }; +} +PackageDatabase::PackageDatabase() : + PrivateImplementationPattern<PackageDatabase>(new Implementation<PackageDatabase>) +{ +} + +PackageDatabase::~PackageDatabase() +{ +} + +void +PackageDatabase::add_repository(const Repository::ConstPointer r) +{ + Context c("When adding a repository named '" + stringify(r->name()) + "':"); + + IndirectIterator<std::list<Repository::ConstPointer>::const_iterator, const Repository> + r_c(_implementation->repositories.begin()), + r_end(_implementation->repositories.end()); + for ( ; r_c != r_end ; ++r_c) + if (r_c->name() == r->name()) + throw DuplicateRepositoryError(stringify(r->name())); + + _implementation->repositories.push_back(r); +} + +VersionMetadata::ConstPointer +PackageDatabase::fetch_metadata(const PackageDatabaseEntry & e) const +{ + const Repository::ConstPointer rr(fetch_repository(e.get<pde_repository>())); + if (! rr->has_category_named(e.get<pde_package>().get<qpn_category>())) + throw NoSuchPackageError(stringify(e.get<pde_package>())); + if (! rr->has_package_named(e.get<pde_package>())) + throw NoSuchPackageError(stringify(e.get<pde_package>())); + if (! rr->has_version(e.get<pde_package>(), e.get<pde_version>())) + throw NoSuchVersionError(stringify(e.get<pde_package>()), e.get<pde_version>()); + return rr->version_metadata(e.get<pde_package>().get<qpn_category>(), + e.get<pde_package>().get<qpn_package>(), e.get<pde_version>()); +} + +Repository::ConstPointer +PackageDatabase::fetch_repository(const RepositoryName & n) const +{ + std::list<Repository::ConstPointer>::const_iterator + r(_implementation->repositories.begin()), + r_end(_implementation->repositories.end()); + for ( ; r != r_end ; ++r) + if ((*r)->name() == n) + return *r; + + throw NoSuchRepositoryError(stringify(n)); +} + +QualifiedPackageName +PackageDatabase::fetch_unique_qualified_package_name( + const PackageNamePart & p) const +{ + QualifiedPackageNameCollection::Pointer result(new QualifiedPackageNameCollection); + + IndirectIterator<std::list<Repository::ConstPointer>::const_iterator, const Repository> + r(_implementation->repositories.begin()), + r_end(_implementation->repositories.end()); + for ( ; r != r_end ; ++r) + { + CategoryNamePartCollection::ConstPointer cats(r->category_names()); + CategoryNamePartCollection::Iterator c(cats->begin()), c_end(cats->end()); + for ( ; c != c_end ; ++c) + if (r->has_package_named(*c, p)) + result->insert(QualifiedPackageName(*c, p)); + } + + if (result->empty()) + throw NoSuchPackageError(stringify(p)); + if (result->size() > 1) + throw AmbiguousPackageNameError(stringify(p), result->begin(), result->end()); + + return *(result->begin()); +} + +PackageDatabaseEntryCollection::Pointer +PackageDatabase::query(const PackageDepAtom * const a) const +{ + PackageDatabaseEntryCollection::Pointer result(new PackageDatabaseEntryCollection); + + IndirectIterator<std::list<Repository::ConstPointer>::const_iterator, const Repository> + r(_implementation->repositories.begin()), + r_end(_implementation->repositories.end()); + for ( ; r != r_end ; ++r) + { + if (! r->has_category_named(a->package().get<qpn_category>())) + continue; + + if (! r->has_package_named(a->package())) + continue; + + VersionSpecCollection::ConstPointer versions(r->version_specs(a->package())); + VersionSpecCollection::Iterator v(versions->begin()), v_end(versions->end()); + for ( ; v != v_end ; ++v) + { + if (a->version_spec_ptr()) + if (! ((*v).*(a->version_operator().as_version_spec_operator()))(*a->version_spec_ptr())) + continue; + + /// \bug SLOT etc + + if (! result->insert(PackageDatabaseEntry(a->package(), *v, r->name()))) + ; /// \bug exception + } + } + + + return result; +} + +const RepositoryName & +PackageDatabase::better_repository(const RepositoryName & r1, + const RepositoryName & r2) const +{ + IndirectIterator<std::list<Repository::ConstPointer>::const_iterator, const Repository> + r(_implementation->repositories.begin()), + r_end(_implementation->repositories.end()); + for ( ; r != r_end ; ++r) + { + if (r->name() == r1) + return r2; + else if (r->name() == r2) + return r1; + } + + throw "TODO"; /// \bug +} + +RepositoryName +PackageDatabase::favourite_repository() const +{ + if (_implementation->repositories.empty()) + return RepositoryName("unnamed"); + else + return (*_implementation->repositories.begin())->name(); +} + +PackageDatabaseEntryCollection::Pointer +PackageDatabase::query(PackageDepAtom::ConstPointer a) const +{ + return query(a.raw_pointer()); +} + +PackageDatabase::RepositoryIterator +PackageDatabase::begin_repositories() const +{ + return _implementation->repositories.begin(); +} + +PackageDatabase::RepositoryIterator +PackageDatabase::end_repositories() const +{ + return _implementation->repositories.end(); +} diff --git a/paludis/package_database.hh b/paludis/package_database.hh new file mode 100644 index 000000000..7fcdad21b --- /dev/null +++ b/paludis/package_database.hh @@ -0,0 +1,116 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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_PACKAGE_DATABASE_HH +#define PALUDIS_GUARD_PALUDIS_PACKAGE_DATABASE_HH 1 + +#include <paludis/instantiation_policy.hh> +#include <paludis/private_implementation_pattern.hh> +#include <paludis/counted_ptr.hh> +#include <paludis/repository.hh> +#include <paludis/version_metadata.hh> +#include <paludis/package_database_entry.hh> +#include <paludis/package_database_entry_collection.hh> +#include <paludis/package_dep_atom.hh> +#include <paludis/repository.hh> + +namespace paludis +{ + class PackageDepAtom; + class PackageDatabase; + + /** + * A PackageDatabase can be queried for Package instances. + */ + class PackageDatabase : + private PrivateImplementationPattern<PackageDatabase>, + private InstantiationPolicy<PackageDatabase, instantiation_method::NonCopyableTag>, + public InternalCounted<PackageDatabase> + { + public: + /** + * Constructor. + */ + PackageDatabase(); + + /** + * Destructor. + */ + ~PackageDatabase(); + + /** + * Add a repository. + * + * \exception DuplicateRepositoryError if a Repository with the + * same name as the new Repository already exists in our + * collection. + */ + void add_repository(Repository::ConstPointer); + + /** + * Fetch the version metadata for a particular item. + */ + VersionMetadata::ConstPointer fetch_metadata(const PackageDatabaseEntry &) const; + + /** + * Fetch a named repository. + */ + Repository::ConstPointer fetch_repository(const RepositoryName &) const; + + /** + * Fetch the name of our 'favourite' repository (if a repository's + * name matches this when doing a graphical display, the repository + * name part may be omitted). + */ + RepositoryName favourite_repository() const; + + /** + * Disambiguate a package name. + */ + QualifiedPackageName fetch_unique_qualified_package_name( + const PackageNamePart &) const; + + /** + * Query the repository. + */ + PackageDatabaseEntryCollection::Pointer query( + const PackageDepAtom * const a) const; + + /** + * Query the repository (overload for a CountedPtr) + */ + PackageDatabaseEntryCollection::Pointer query( + PackageDepAtom::ConstPointer a) const; + + /** + * Which repository is better? + */ + const RepositoryName & better_repository(const RepositoryName &, + const RepositoryName &) const; + + + typedef std::list<Repository::ConstPointer>::const_iterator RepositoryIterator; + + RepositoryIterator begin_repositories() const; + + RepositoryIterator end_repositories() const; + }; +} + +#endif diff --git a/paludis/package_database_TEST.cc b/paludis/package_database_TEST.cc new file mode 100644 index 000000000..82500297f --- /dev/null +++ b/paludis/package_database_TEST.cc @@ -0,0 +1,197 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +/* + * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@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. + * |