aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-04 05:12:44 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-04 05:12:44 +0000
commit7e97ae154ccfdcc61dce79dcff3574d261a9ca39 (patch)
tree753db9efacdeb3123e716fb9d148cff6aa5dbcd5
parent00d07ad717b23f89541aceae012084de47b28f46 (diff)
downloadpaludis-7e97ae154ccfdcc61dce79dcff3574d261a9ca39.tar.gz
paludis-7e97ae154ccfdcc61dce79dcff3574d261a9ca39.tar.xz
Re-add Gems, using Syck instead of libyaml. Various code cleanups.
-rw-r--r--configure.ac35
-rw-r--r--paludis/dep_list/dep_list.cc4
-rw-r--r--paludis/eapi.cc18
-rw-r--r--paludis/environments/paludis/mirrors_conf.cc4
-rw-r--r--paludis/environments/paludis/paludis_environment.cc2
-rw-r--r--paludis/environments/portage/portage_environment.cc3
-rw-r--r--paludis/merger/merger_TEST.cc2
-rw-r--r--paludis/qa/dep_flags_check.cc3
-rw-r--r--paludis/qa/iuse_check.cc4
-rw-r--r--paludis/repositories/fake/fake_repository_base.cc5
-rw-r--r--paludis/repositories/gems/Makefile.am152
-rw-r--r--paludis/repositories/gems/exceptions.cc29
-rw-r--r--paludis/repositories/gems/exceptions.hh38
-rw-r--r--paludis/repositories/gems/gem_specification-fwd.hh32
-rw-r--r--paludis/repositories/gems/gem_specification.cc229
-rw-r--r--paludis/repositories/gems/gem_specification.hh62
-rw-r--r--paludis/repositories/gems/gem_specification_TEST.cc66
-rw-r--r--paludis/repositories/gems/gem_specifications.cc200
-rw-r--r--paludis/repositories/gems/gem_specifications.hh55
-rw-r--r--paludis/repositories/gems/gem_specifications_TEST.cc41
-rwxr-xr-xpaludis/repositories/gems/gems.bash55
-rw-r--r--paludis/repositories/gems/gems_repository.cc256
-rw-r--r--paludis/repositories/gems/gems_repository.hh79
-rw-r--r--paludis/repositories/gems/gems_repository_TEST.cc51
-rwxr-xr-xpaludis/repositories/gems/gems_repository_TEST_cleanup.sh9
-rwxr-xr-xpaludis/repositories/gems/gems_repository_TEST_setup.sh6
-rw-r--r--paludis/repositories/gems/installed_gems_repository.cc319
-rw-r--r--paludis/repositories/gems/installed_gems_repository.hh94
-rw-r--r--paludis/repositories/gems/installed_gems_repository_TEST.cc49
-rwxr-xr-xpaludis/repositories/gems/installed_gems_repository_TEST_cleanup.sh9
-rwxr-xr-xpaludis/repositories/gems/installed_gems_repository_TEST_setup.sh6
-rw-r--r--paludis/repositories/gems/metadata.cc87
-rw-r--r--paludis/repositories/gems/metadata.hh66
-rw-r--r--paludis/repositories/gems/params-fwd.hh32
-rw-r--r--paludis/repositories/gems/params.cc26
-rw-r--r--paludis/repositories/gems/params.hh41
-rw-r--r--paludis/repositories/gems/params.sr27
-rw-r--r--paludis/repositories/gems/registration.cc91
-rw-r--r--paludis/repositories/gems/yaml-fwd.hh38
-rw-r--r--paludis/repositories/gems/yaml.cc364
-rw-r--r--paludis/repositories/gems/yaml.hh137
-rw-r--r--paludis/repositories/gems/yaml_TEST.cc185
-rw-r--r--paludis/repositories/gentoo/traditional_layout.cc11
-rw-r--r--paludis/repositories/gentoo/vdb_unmerger.cc2
-rw-r--r--paludis/repositories/virtuals/virtuals_repository.cc3
-rw-r--r--paludis/util/Makefile.am.m42
-rw-r--r--paludis/util/iterator.hh38
-rw-r--r--paludis/util/iterator_TEST.cc19
-rw-r--r--paludis/util/options.cc4
-rw-r--r--paludis/util/private_implementation_pattern-impl.hh14
-rw-r--r--paludis/util/private_implementation_pattern.hh3
-rw-r--r--paludis/util/tr1_functional.hh3
-rw-r--r--paludis/util/virtual_constructor-impl.hh5
-rw-r--r--src/output/use_flag_pretty_printer.cc7
54 files changed, 3035 insertions, 87 deletions
diff --git a/configure.ac b/configure.ac
index fb80939..5184f34 100644
--- a/configure.ac
+++ b/configure.ac
@@ -325,6 +325,8 @@ dnl }}}
need_xml_check=
need_pcrepp_check=
+need_syck_check=
+need_gem_check=
dnl {{{ we need libebt.
dnl don't use AC_CHECK_HEADER, it does silly things
@@ -842,7 +844,7 @@ AC_SUBST([VIM_INSTALL_DIR])
dnl }}}
dnl {{{ repositories
-ALL_REPOSITORIES="cran fake gentoo virtuals"
+ALL_REPOSITORIES="cran fake gems gentoo virtuals"
DEFAULT_REPOSITORIES="fake gentoo virtuals"
AC_MSG_CHECKING([which repositories to build...])
AC_ARG_WITH([repositories],
@@ -850,8 +852,9 @@ AC_ARG_WITH([repositories],
Build the specified repositories:
default Equivalent to fake,gentoo,virtuals
- cran The Comprehensive R Archive Network
+ cran The Comprehensive R Archive Network (experimental)
fake A fake repository for test cases and adjutrix
+ gems Ruby gems (experimental)
gentoo Gentoo packages (ebuilds, vdb)
virtuals Old style Gentoo virtuals],
[repositories="`echo $with_repositories | tr ',' ' '`"],
@@ -861,6 +864,11 @@ AC_MSG_RESULT([$repositories])
BUILD_REPOSITORIES="$repositories"
AC_SUBST([ALL_REPOSITORIES])
AC_SUBST([BUILD_REPOSITORIES])
+
+if echo $repositories | tr ' ' '\n' | grep '^gems$' >/dev/null ; then
+ need_syck_check=yes
+ need_gem_check=yes
+fi
dnl }}}
dnl {{{ environments
@@ -954,6 +962,28 @@ if test "x$need_pcrepp_check" = "xyes" ; then
fi
dnl }}}
+dnl {{{ syck check
+if test "x$need_syck_check" = "xyes" ; then
+ AC_MSG_CHECKING([for syck])
+ AC_COMPILE_IFELSE([
+#include <syck.h>
+],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_ERROR([syck is required for gems repositories])])
+fi
+dnl }}}
+
+dnl {{{ gem check
+if test "x$need_gem_check" = "xyes" ; then
+ AC_MSG_CHECKING([for gem])
+ if gem -v 1>/dev/null 2>/dev/null ; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_ERROR([gem (http://rubygems.org/) is required for gems repositories])
+ fi
+fi
+dnl }}}
+
dnl {{{ is sed gnu sed
AC_MSG_CHECKING([if we need a sed wrapper])
AC_SUBST([NEED_SED_WRAPPER])
@@ -1092,6 +1122,7 @@ AC_OUTPUT(
paludis/repositories/cran/Makefile
paludis/repositories/cran/cran/Makefile
paludis/repositories/fake/Makefile
+ paludis/repositories/gems/Makefile
paludis/repositories/gentoo/Makefile
paludis/repositories/gentoo/ebuild/Makefile
paludis/repositories/gentoo/ebuild/digests/Makefile
diff --git a/paludis/dep_list/dep_list.cc b/paludis/dep_list/dep_list.cc
index 457428f..02a9dff 100644
--- a/paludis/dep_list/dep_list.cc
+++ b/paludis/dep_list/dep_list.cc
@@ -990,7 +990,7 @@ DepList::add_package(const PackageDatabaseEntry & p, tr1::shared_ptr<const DepTa
.generation(_imp->merge_list_generation)
.state(dle_no_deps)
.tags(tr1::shared_ptr<DepListEntryTags>(new DepListEntryTags::Concrete))
- .destination(find_destination(p, destinations))
+ .destination(metadata->virtual_interface ? tr1::shared_ptr<Repository>() : find_destination(p, destinations))
.associated_entry(0)
.kind(metadata->virtual_interface ? dlk_virtual : dlk_package))),
our_merge_entry_post_position(our_merge_entry_position);
@@ -1407,7 +1407,7 @@ DepList::prefer_installed_over_uninstalled(const PackageDatabaseEntry & installe
evm_i->iuse()->begin(), evm_i->iuse()->end(),
evm_u->iuse()->begin(), evm_u->iuse()->end(),
transform_inserter(std::inserter(use_common, use_common.end()),
- SelectMember<IUseFlag, UseFlagName, &IUseFlag::flag>()));
+ paludis::tr1::mem_fn(&IUseFlag::flag)));
for (std::set<UseFlagName>::const_iterator f(use_common.begin()), f_end(use_common.end()) ;
f != f_end ; ++f)
diff --git a/paludis/eapi.cc b/paludis/eapi.cc
index 5e32c4e..1dd2be3 100644
--- a/paludis/eapi.cc
+++ b/paludis/eapi.cc
@@ -139,6 +139,24 @@ namespace paludis
.ebuild_metadata_variables(tr1::shared_ptr<EAPIEbuildMetadataVariables>())
.ebuild_phases(tr1::shared_ptr<EAPIEbuildPhases>())
))))));
+
+ values.insert(std::make_pair("gems-1",
+ make_shared_ptr(new EAPI("gems-1", make_shared_ptr(new SupportedEAPI(
+ SupportedEAPI::create()
+ .package_dep_spec_parse_mode(pds_pm_permissive)
+ .strict_package_dep_spec_parse_mode(pds_pm_permissive)
+ .dependency_spec_tree_parse_mode(dst_pm_eapi_0)
+ .iuse_flag_parse_mode(iuse_pm_permissive)
+ .strict_iuse_flag_parse_mode(iuse_pm_permissive)
+ .breaks_portage(true)
+ .uri_supports_arrow(false)
+ .want_aa_var(false)
+ .want_arch_var(false)
+ .want_portage_emulation_vars(false)
+ .require_use_expand_in_iuse(false)
+ .ebuild_metadata_variables(tr1::shared_ptr<EAPIEbuildMetadataVariables>())
+ .ebuild_phases(tr1::shared_ptr<EAPIEbuildPhases>())
+ ))))));
}
};
}
diff --git a/paludis/environments/paludis/mirrors_conf.cc b/paludis/environments/paludis/mirrors_conf.cc
index 421841e..b219e0d 100644
--- a/paludis/environments/paludis/mirrors_conf.cc
+++ b/paludis/environments/paludis/mirrors_conf.cc
@@ -28,6 +28,7 @@
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/tokeniser.hh>
#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tr1_functional.hh>
#include <vector>
using namespace paludis;
@@ -87,7 +88,8 @@ MirrorsConf::query(const std::string & m) const
{
tr1::shared_ptr<MirrorsCollection> result(new MirrorsCollection::Concrete);
std::pair<Mirrors::const_iterator, Mirrors::const_iterator> p(_imp->mirrors.equal_range(m));
- std::copy(p.first, p.second, transform_inserter(result->inserter(), SelectSecond<std::string, std::string>()));
+ std::copy(p.first, p.second, transform_inserter(result->inserter(),
+ paludis::tr1::mem_fn(&std::pair<const std::string, std::string>::second)));
return result;
}
diff --git a/paludis/environments/paludis/paludis_environment.cc b/paludis/environments/paludis/paludis_environment.cc
index 90b7434..33df225 100644
--- a/paludis/environments/paludis/paludis_environment.cc
+++ b/paludis/environments/paludis/paludis_environment.cc
@@ -292,7 +292,7 @@ PaludisEnvironment::hook_dirs() const
tr1::shared_ptr<FSEntryCollection> result(new FSEntryCollection::Concrete);
std::copy(_imp->hook_dirs.begin(), _imp->hook_dirs.end(),
- transform_inserter(result->inserter(), SelectFirst<FSEntry, bool>()));
+ transform_inserter(result->inserter(), tr1::mem_fn(&std::pair<FSEntry, bool>::first)));
return result;
}
diff --git a/paludis/environments/portage/portage_environment.cc b/paludis/environments/portage/portage_environment.cc
index 055efa3..f7bffb8 100644
--- a/paludis/environments/portage/portage_environment.cc
+++ b/paludis/environments/portage/portage_environment.cc
@@ -655,7 +655,8 @@ PortageEnvironment::mirrors(const std::string & m) const
std::pair<std::multimap<std::string, std::string>::const_iterator, std::multimap<std::string, std::string>::const_iterator>
p(_imp->mirrors.equal_range(m));
tr1::shared_ptr<MirrorsCollection> result(new MirrorsCollection::Concrete);
- std::copy(p.first, p.second, transform_inserter(result->inserter(), SelectSecond<std::string, std::string>()));
+ std::copy(p.first, p.second, transform_inserter(result->inserter(),
+ tr1::mem_fn(&std::pair<const std::string, std::string>::second)));
return result;
}
diff --git a/paludis/merger/merger_TEST.cc b/paludis/merger/merger_TEST.cc
index e192587..8afdd1b 100644
--- a/paludis/merger/merger_TEST.cc
+++ b/paludis/merger/merger_TEST.cc
@@ -35,7 +35,7 @@ namespace paludis
public TestEnvironment
{
private:
- mutable std::tr1::shared_ptr<Hooker> hooker;
+ mutable tr1::shared_ptr<Hooker> hooker;
mutable std::list<std::pair<FSEntry, bool> > hook_dirs;
public:
diff --git a/paludis/qa/dep_flags_check.cc b/paludis/qa/dep_flags_check.cc
index 8c977c6..bc1b8a2 100644
--- a/paludis/qa/dep_flags_check.cc
+++ b/paludis/qa/dep_flags_check.cc
@@ -26,6 +26,7 @@
#include <paludis/util/visitor-impl.hh>
#include <paludis/qa/qa_environment.hh>
#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/tr1_functional.hh>
#include <set>
#include <algorithm>
@@ -150,7 +151,7 @@ DepFlagsCheck::operator() (const EbuildCheckData & e) const
std::set<UseFlagName> iuse;
std::copy(metadata->ebuild_interface->iuse()->begin(), metadata->ebuild_interface->iuse()->end(),
transform_inserter(std::inserter(iuse, iuse.begin()),
- SelectMember<IUseFlag, UseFlagName, &IUseFlag::flag>()));
+ tr1::mem_fn(&IUseFlag::flag)));
iuse.insert(UseFlagName("bootstrap"));
iuse.insert(UseFlagName("build"));
diff --git a/paludis/qa/iuse_check.cc b/paludis/qa/iuse_check.cc
index 6c4d450..af03b81 100644
--- a/paludis/qa/iuse_check.cc
+++ b/paludis/qa/iuse_check.cc
@@ -28,6 +28,7 @@
#include <paludis/util/log.hh>
#include <paludis/util/system.hh>
#include <paludis/util/iterator.hh>
+#include <paludis/util/tr1_functional.hh>
#include <paludis/qa/qa_environment.hh>
#include <algorithm>
@@ -59,8 +60,7 @@ IuseCheck::operator() (const EbuildCheckData & e) const
{
std::set<UseFlagName> iuse;
std::copy(metadata->ebuild_interface->iuse()->begin(), metadata->ebuild_interface->iuse()->end(),
- transform_inserter(std::inserter(iuse, iuse.begin()),
- SelectMember<IUseFlag, UseFlagName, &IUseFlag::flag>()));
+ transform_inserter(std::inserter(iuse, iuse.begin()), tr1::mem_fn(&IUseFlag::flag)));
static std::set<UseFlagName> iuse_blacklist;
if (iuse_blacklist.empty())
diff --git a/paludis/repositories/fake/fake_repository_base.cc b/paludis/repositories/fake/fake_repository_base.cc
index 0c47dae..602fce5 100644
--- a/paludis/repositories/fake/fake_repository_base.cc
+++ b/paludis/repositories/fake/fake_repository_base.cc
@@ -23,6 +23,7 @@
#include <paludis/util/iterator.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/tr1_functional.hh>
#include <paludis/version_metadata.hh>
#include <paludis/portage_dep_parser.hh>
#include <paludis/eapi.hh>
@@ -269,8 +270,8 @@ tr1::shared_ptr<const SetNameCollection>
FakeRepositoryBase::sets_list() const
{
tr1::shared_ptr<SetNameCollection> result(new SetNameCollection::Concrete);
- std::copy(_imp->sets.begin(), _imp->sets.end(),
- transform_inserter(result->inserter(), SelectFirst<SetName, tr1::shared_ptr<SetSpecTree::ConstItem> >()));
+ std::copy(_imp->sets.begin(), _imp->sets.end(), transform_inserter(result->inserter(),
+ tr1::mem_fn(&std::pair<const SetName, tr1::shared_ptr<SetSpecTree::ConstItem> >::first)));
return result;
}
diff --git a/paludis/repositories/gems/Makefile.am b/paludis/repositories/gems/Makefile.am
new file mode 100644
index 0000000..9cf0218
--- /dev/null
+++ b/paludis/repositories/gems/Makefile.am
@@ -0,0 +1,152 @@
+SUBDIRS = .
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = params-sr.hh params-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) -I$(top_builddir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS = \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+paludis_gems_libexecdir = $(libexecdir)/paludis/gems
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisgemsrepository.la
+
+paludis_repositories_gems_includedir = $(includedir)/paludis/repositories/gems/
+libpaludisgemsrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_gems_include_HEADERS = \
+ gems_repository.hh \
+ installed_gems_repository.hh \
+ metadata.hh \
+ exceptions.hh \
+ yaml.hh yaml-fwd.hh \
+ gem_specification.hh gem_specification-fwd.hh \
+ gem_specifications.hh \
+ params-fwd.hh params.hh params-sr.hh
+
+libpaludisgemsrepository_la_SOURCES = \
+ gems_repository.cc \
+ installed_gems_repository.cc \
+ params.cc \
+ metadata.cc \
+ exceptions.cc \
+ yaml.cc \
+ gem_specification.cc \
+ gem_specifications.cc \
+ registration.cc \
+ $(paludis_repositories_gems_include_HEADERS)
+
+libpaludisgemsrepository_la_LIBADD = \
+ $(top_builddir)/paludis/repositories/libpaludisrepositories.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ -lsyck
+
+gems_repository_TEST_SOURCES = gems_repository_TEST.cc
+installed_gems_repository_TEST_SOURCES = gems_repository_TEST.cc
+yaml_TEST_SOURCES = yaml_TEST.cc
+gem_specification_TEST_SOURCES = gem_specification_TEST.cc
+gem_specifications_TEST_SOURCES = gem_specifications_TEST.cc
+
+gems_repository_TEST_LDADD = \
+ libpaludisgemsrepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ -lsyck
+
+installed_gems_repository_TEST_LDADD = \
+ libpaludisgemsrepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ -lsyck
+
+yaml_TEST_LDADD = \
+ libpaludisgemsrepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ -lsyck
+
+gem_specification_TEST_LDADD = \
+ libpaludisgemsrepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ -lsyck
+
+gem_specifications_TEST_LDADD = \
+ libpaludisgemsrepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ -lsyck
+
+gems_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+installed_gems_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+yaml_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+gem_specification_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+gem_specifications_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+EXTRA_DIST = \
+ installed_gems_repository_TEST.cc \
+ installed_gems_repository_TEST_setup.sh \
+ installed_gems_repository_TEST_cleanup.sh \
+ gems_repository_TEST.cc \
+ gems_repository_TEST_setup.sh \
+ gems_repository_TEST_cleanup.sh \
+ yaml_TEST.cc \
+ gem_specification_TEST.cc \
+ gem_specifications_TEST.cc \
+ params-sr.hh \
+ params-sr.cc \
+ params.sr
+
+BUILT_SOURCES = \
+ params-sr.hh params-sr.cc
+
+check_SCRIPTS = \
+ gems_repository_TEST_setup.sh gems_repository_TEST_cleanup.sh
+
+paludis_gems_libexec_SCRIPTS = gems.bash
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_GEMS_DIR="`$(top_srcdir)/paludis/repositories/gentoo/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/gems/`" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/eapis/" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ LD_LIBRARY_PATH="`echo $$LD_LIBRARY_PATH: | sed -e 's,^:,,'`` \
+ $(top_srcdir)/paludis/repositories/gentoo/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/gems/`:` \
+ $(top_srcdir)/paludis/repositories/gentoo/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/gems/.libs/`" \
+ bash $(top_srcdir)/test/run_test.sh
+
+TESTS = gems_repository_TEST installed_gems_repository_TEST yaml_TEST gem_specification_TEST gem_specifications_TEST
+check_PROGRAMS = $(TESTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+params-sr.hh : params.sr $(top_srcdir)/misc/make_sr.bash
+ if ! $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/params.sr > $@ ; then rm -f $@ ; exit 1 ; fi
+
+params-sr.cc : params.sr $(top_srcdir)/misc/make_sr.bash
+ if ! $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/params.sr > $@ ; then rm -f $@ ; exit 1 ; fi
+
+
diff --git a/paludis/repositories/gems/exceptions.cc b/paludis/repositories/gems/exceptions.cc
new file mode 100644
index 0000000..77440d5
--- /dev/null
+++ b/paludis/repositories/gems/exceptions.cc
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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 "exceptions.hh"
+
+using namespace paludis;
+using namespace paludis::gems;
+
+RepositoryConfigurationError::RepositoryConfigurationError(const std::string & s) throw () :
+ ConfigurationError(s)
+{
+}
+
diff --git a/paludis/repositories/gems/exceptions.hh b/paludis/repositories/gems/exceptions.hh
new file mode 100644
index 0000000..acd6d3e
--- /dev/null
+++ b/paludis/repositories/gems/exceptions.hh
@@ -0,0 +1,38 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_EXCEPTIONS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_EXCEPTIONS_HH 1
+
+#include <paludis/util/exception.hh>
+
+namespace paludis
+{
+ namespace gems
+ {
+ class PALUDIS_VISIBLE RepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ RepositoryConfigurationError(const std::string &) throw ();
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/gem_specification-fwd.hh b/paludis/repositories/gems/gem_specification-fwd.hh
new file mode 100644
index 0000000..0e8317a
--- /dev/null
+++ b/paludis/repositories/gems/gem_specification-fwd.hh
@@ -0,0 +1,32 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_GEM_SPECIFICATION_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_GEM_SPECIFICATION_FWD_HH 1
+
+namespace paludis
+{
+ namespace gems
+ {
+ class BadSpecificationError;
+ class GemSpecification;
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/gem_specification.cc b/paludis/repositories/gems/gem_specification.cc
new file mode 100644
index 0000000..9425608
--- /dev/null
+++ b/paludis/repositories/gems/gem_specification.cc
@@ -0,0 +1,229 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/repositories/gems/gem_specification.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/tr1_functional.hh>
+
+using namespace paludis;
+using namespace paludis::gems;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<GemSpecification>
+ {
+ std::string name;
+ std::string version;
+ std::string summary;
+ std::string authors;
+ std::string date;
+ std::string description;
+ std::string platform;
+ std::string rubyforge_project;
+ std::string homepage;
+ };
+}
+
+namespace
+{
+ std::string extract_text_only(const yaml::Node & n, const std::string & extra);
+
+ struct VersionVisitor :
+ ConstVisitor<yaml::NodeVisitorTypes>
+ {
+ std::string text;
+
+ void visit(const yaml::StringNode & n) PALUDIS_ATTRIBUTE((noreturn));
+ void visit(const yaml::SequenceNode & n) PALUDIS_ATTRIBUTE((noreturn));
+
+ void visit(const yaml::MapNode & n)
+ {
+ yaml::MapNode::Iterator i(n.find("version"));
+ if (i == n.end())
+ throw BadSpecificationError("Version has no version: key");
+ text = extract_text_only(*i->second, "for Version version: key");
+ }
+ };
+
+ void VersionVisitor::visit(const yaml::StringNode &)
+ {
+ throw BadSpecificationError("Version child node is string, not map");
+ }
+
+ void VersionVisitor::visit(const yaml::SequenceNode &)
+ {
+ throw BadSpecificationError("Version child node is sequence, not map");
+ }
+
+ struct ExtractTextVisitor :
+ ConstVisitor<yaml::NodeVisitorTypes>
+ {
+ const std::string extra;
+ const bool accept_sequence;
+ std::string result;
+
+ ExtractTextVisitor(const std::string & s, const bool b) :
+ extra(s),
+ accept_sequence(b)
+ {
+ }
+
+ void visit(const yaml::StringNode & n)
+ {
+ result = n.text();
+ }
+
+ void visit(const yaml::SequenceNode & s)
+ {
+ if (! accept_sequence)
+ throw BadSpecificationError("Found sequence rather than text " + extra);
+
+ bool w(false);
+ for (yaml::SequenceNode::Iterator i(s.begin()), i_end(s.end()) ; i != i_end ; ++i)
+ {
+ if (w)
+ result.append(", ");
+ result.append(extract_text_only(**i, extra));
+ w = true;
+ }
+ }
+
+ void visit(const yaml::MapNode &) PALUDIS_ATTRIBUTE((noreturn));
+ };
+
+ void ExtractTextVisitor::visit(const yaml::MapNode &)
+ {
+ throw BadSpecificationError("Found map rather than text " + extra);
+ }
+
+ std::string extract_text_only(const yaml::Node & n, const std::string & extra)
+ {
+ ExtractTextVisitor v(extra, false);
+ n.accept(v);
+ return v.result;
+ }
+
+ std::string extract_text_sequence(const yaml::Node & n, const std::string & extra)
+ {
+ ExtractTextVisitor v(extra, true);
+ n.accept(v);
+ return v.result;
+ }
+
+ std::string required_text_only_key(const yaml::MapNode & n, const std::string & k)
+ {
+ yaml::MapNode::Iterator i(n.find(k));
+ if (i == n.end())
+ throw BadSpecificationError("Key '" + k + "' not defined");
+ return extract_text_only(*i->second, "for key '" + k + "'");
+ }
+
+ std::string optional_text_sequence_key(const yaml::MapNode & n, const std::string & k)
+ {
+ yaml::MapNode::Iterator i(n.find(k));
+ if (i == n.end())
+ return "";
+ return extract_text_sequence(*i->second, "for key '" + k + "'");
+ }
+
+ std::string optional_text_only_key(const yaml::MapNode & n, const std::string & k)
+ {
+ yaml::MapNode::Iterator i(n.find(k));
+ if (i == n.end())
+ return "";
+ return extract_text_only(*i->second, "for key '" + k + "'");
+ }
+
+ std::string required_version(const yaml::MapNode & n, const std::string & k)
+ {
+ yaml::MapNode::Iterator i(n.find(k));
+ if (i == n.end())
+ throw BadSpecificationError("Key '" + k + "' not defined");
+
+ VersionVisitor v;
+ i->second->accept(v);
+ return v.text;
+ }
+
+ struct TopVisitor :
+ ConstVisitor<yaml::NodeVisitorTypes>
+ {
+ Implementation<GemSpecification> * const _imp;
+
+ TopVisitor(Implementation<GemSpecification> * const i) :
+ _imp(i)
+ {
+ }
+
+ void visit(const yaml::MapNode & n)
+ {
+ _imp->summary = required_text_only_key(n, "summary");
+ _imp->authors = optional_text_sequence_key(n, "authors");
+ _imp->date = required_text_only_key(n, "date");
+ _imp->description = optional_text_only_key(n, "description");
+ _imp->platform = required_text_only_key(n, "platform");
+ _imp->name = required_text_only_key(n, "name");
+ _imp->version = required_version(n, "version");
+ _imp->rubyforge_project = optional_text_sequence_key(n, "rubyforge_project");
+ }
+
+ void visit(const yaml::SequenceNode & n) PALUDIS_ATTRIBUTE((noreturn));
+
+ void visit(const yaml::StringNode & n) PALUDIS_ATTRIBUTE((noreturn));
+ };
+
+ void TopVisitor::visit(const yaml::SequenceNode &)
+ {
+ throw BadSpecificationError("Top level node is sequence, not map");
+ }
+
+ void TopVisitor::visit(const yaml::StringNode & n)
+ {
+ throw BadSpecificationError("Top level node is text '" + n.text() + "', not map");
+ }
+}
+
+GemSpecification::GemSpecification(const yaml::Node & node) :
+ PrivateImplementationPattern<GemSpecification>(new Implementation<GemSpecification>),
+ name(tr1::bind(&Implementation<GemSpecification>::name, _imp.get())),
+ version(tr1::bind(&Implementation<GemSpecification>::version, _imp.get())),
+ homepage(tr1::bind(&Implementation<GemSpecification>::homepage, _imp.get())),
+ rubyforge_project(tr1::bind(&Implementation<GemSpecification>::rubyforge_project, _imp.get())),
+ authors(tr1::bind(&Implementation<GemSpecification>::authors, _imp.get())),
+ date(tr1::bind(&Implementation<GemSpecification>::date, _imp.get())),
+ platform(tr1::bind(&Implementation<GemSpecification>::platform, _imp.get())),
+ summary(tr1::bind(&Implementation<GemSpecification>::summary, _imp.get())),
+ description(tr1::bind(&Implementation<GemSpecification>::description, _imp.get()))
+{
+ TopVisitor v(_imp.get());
+ node.accept(v);
+}
+
+GemSpecification::~GemSpecification()
+{
+}
+
+BadSpecificationError::BadSpecificationError(const std::string & s) throw () :
+ Exception("Bad gem specification: " + s)
+{
+}
+
diff --git a/paludis/repositories/gems/gem_specification.hh b/paludis/repositories/gems/gem_specification.hh
new file mode 100644
index 0000000..37ac015
--- /dev/null
+++ b/paludis/repositories/gems/gem_specification.hh
@@ -0,0 +1,62 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_GEM_SPECIFICATION_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_GEM_SPECIFICATION_HH 1
+
+#include <paludis/repositories/gems/gem_specification-fwd.hh>
+#include <paludis/repositories/gems/yaml-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace gems
+ {
+ class PALUDIS_VISIBLE BadSpecificationError :
+ public Exception
+ {
+ public:
+ BadSpecificationError(const std::string &) throw ();
+ };
+
+ class PALUDIS_VISIBLE GemSpecification :
+ private PrivateImplementationPattern<GemSpecification>
+ {
+ public:
+ GemSpecification(const yaml::Node &);
+ ~GemSpecification();
+
+ const tr1::function<std::string ()> name;
+ const tr1::function<std::string ()> version;
+ const tr1::function<std::string ()> homepage;
+ const tr1::function<std::string ()> rubyforge_project;
+ const tr1::function<std::string ()> authors;
+ const tr1::function<std::string ()> date;
+ const tr1::function<std::string ()> platform;
+ const tr1::function<std::string ()> summary;
+ const tr1::function<std::string ()> description;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/gem_specification_TEST.cc b/paludis/repositories/gems/gem_specification_TEST.cc
new file mode 100644
index 0000000..4836d9e
--- /dev/null
+++ b/paludis/repositories/gems/gem_specification_TEST.cc
@@ -0,0 +1,66 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_runner.hh>
+#include <test/test_framework.hh>
+#include <paludis/repositories/gems/gem_specification.hh>
+#include <paludis/repositories/gems/yaml.hh>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::gems;
+
+namespace test_cases
+{
+ struct SpecificationTest : TestCase
+ {
+ SpecificationTest() : TestCase("gem specification") { }
+
+ void run()
+ {
+ std::string spec_text(
+ "--- !ruby/object:Gem::Specification\n"
+ "name: demo\n"
+ "version: !ruby/object:Gem::Version\n"
+ " version: 1.2.3\n"
+ "summary: This is the summary\n"
+ "homepage:\n"
+ "rubyforge_project:\n"
+ "description: A longer description\n"
+ "platform: ruby\n"
+ "date: 1234\n"
+ "authors: [ Fred , Barney ]\n"
+ );
+
+ yaml::Document spec_doc(spec_text);
+ TEST_CHECK(spec_doc.top());
+
+ GemSpecification spec(*spec_doc.top());
+ TEST_CHECK_EQUAL(spec.summary(), "This is the summary");
+ TEST_CHECK_EQUAL(spec.name(), "demo");
+ TEST_CHECK_EQUAL(spec.version(), "1.2.3");
+ TEST_CHECK_EQUAL(spec.homepage(), "");
+ TEST_CHECK_EQUAL(spec.rubyforge_project(), "");
+ TEST_CHECK_EQUAL(spec.description(), "A longer description");
+ TEST_CHECK_EQUAL(spec.authors(), "Fred, Barney");
+ TEST_CHECK_EQUAL(spec.date(), "1234");
+ }
+ } test_specification;
+}
+
diff --git a/paludis/repositories/gems/gem_specifications.cc b/paludis/repositories/gems/gem_specifications.cc
new file mode 100644
index 0000000..988adf1
--- /dev/null
+++ b/paludis/repositories/gems/gem_specifications.cc
@@ -0,0 +1,200 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/repositories/gems/gem_specifications.hh>
+#include <paludis/repositories/gems/gem_specification.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/hashed_containers.hh>
+
+using namespace paludis;
+using namespace paludis::gems;
+
+typedef MakeHashedMap<std::pair<QualifiedPackageName, VersionSpec>, tr1::shared_ptr<const GemSpecification> >::Type Specs;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<GemSpecifications>
+ {
+ Specs specs;
+ };
+}
+
+namespace
+{
+ std::string extract_text_only(const yaml::Node & n, const std::string & extra);
+
+ struct ExtractTextVisitor :
+ ConstVisitor<yaml::NodeVisitorTypes>
+ {
+ const std::string extra;
+ const bool accept_sequence;
+ std::string result;
+
+ ExtractTextVisitor(const std::string & s, const bool b) :
+ extra(s),
+ accept_sequence(b)
+ {
+ }
+
+ void visit(const yaml::StringNode & n)
+ {
+ result = n.text();
+ }
+
+ void visit(const yaml::SequenceNode & s)
+ {
+ if (! accept_sequence)
+ throw BadSpecificationError("Found sequence rather than text " + extra);
+
+ bool w(false);
+ for (yaml::SequenceNode::Iterator i(s.begin()), i_end(s.end()) ; i != i_end ; ++i)
+ {
+ if (w)
+ result.append(", ");
+ result.append(extract_text_only(**i, extra));
+ w = true;
+ }
+ }
+
+ void visit(const yaml::MapNode &) PALUDIS_ATTRIBUTE((noreturn));
+ };
+
+ void ExtractTextVisitor::visit(const yaml::MapNode &)
+ {
+ throw BadSpecificationError("Found map rather than text " + extra);
+ }
+
+ std::string extract_text_only(const yaml::Node & n, const std::string & extra)
+ {
+ ExtractTextVisitor v(extra, false);
+ n.accept(v);
+ return v.result;
+ }
+
+ struct GemsVisitor :
+ ConstVisitor<yaml::NodeVisitorTypes>
+ {
+ Implementation<GemSpecifications> * const _imp;
+
+ GemsVisitor(Implementation<GemSpecifications> * const i) :
+ _imp(i)
+ {
+ }
+
+ void visit(const yaml::MapNode & n)
+ {
+ for (yaml::MapNode::Iterator i(n.begin()), i_end(n.end()) ; i != i_end ; ++i)
+ {
+ std::string pv(extract_text_only(*i->first, " as key for gem"));
+ Context c_item("When handling Gem entry '" + pv + "':");
+
+ try
+ {
+ tr1::shared_ptr<GemSpecification> spec(make_shared_ptr(new GemSpecification(*i->second)));
+ _imp->specs.insert(std::make_pair(std::make_pair(CategoryNamePart("gems") + PackageNamePart(spec->name()),
+ VersionSpec(spec->version())), spec));
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_qa, lc_context) << "Skipping entry '"
+ << pv << "' due to exception '" << e.message() << "' (" << e.what() << ")";
+ }
+ }
+ }
+
+ void visit(const yaml::SequenceNode & n) PALUDIS_ATTRIBUTE((noreturn));
+
+ void visit(const yaml::StringNode & n) PALUDIS_ATTRIBUTE((noreturn));
+ };
+
+ void GemsVisitor::visit(const yaml::SequenceNode &)
+ {
+ throw BadSpecificationError("Top level 'gems' right hand node is sequence, not map");
+ }
+
+ void GemsVisitor::visit(const yaml::StringNode & n)
+ {
+ throw BadSpecificationError("Top level 'gems' right hand node is text '" + n.text() + "', not map");
+ }
+
+ struct TopVisitor :
+ ConstVisitor<yaml::NodeVisitorTypes>
+ {
+ Implementation<GemSpecifications> * const _imp;
+
+ TopVisitor(Implementation<GemSpecifications> * const i) :
+ _imp(i)
+ {
+ }
+
+ void visit(const yaml::MapNode & n)
+ {
+ yaml::MapNode::Iterator i(n.find("gems"));
+ if (n.end() == i)
+ throw BadSpecificationError("Top level map does not contain 'gems' node");
+
+ GemsVisitor g(_imp);
+ i->second->accept(g);
+ }
+
+ void visit(const yaml::SequenceNode & n) PALUDIS_ATTRIBUTE((noreturn));
+
+ void visit(const yaml::StringNode & n) PALUDIS_ATTRIBUTE((noreturn));
+ };
+
+ void TopVisitor::visit(const yaml::SequenceNode &)
+ {
+ throw BadSpecificationError("Top level node is sequence, not map");
+ }
+
+ void TopVisitor::visit(const yaml::StringNode & n)
+ {
+ throw BadSpecificationError("Top level node is text '" + n.text() + "', not map");
+ }
+}
+
+GemSpecifications::GemSpecifications(const yaml::Node & n) :
+ PrivateImplementationPattern<GemSpecifications>(new Implementation<GemSpecifications>)
+{
+ TopVisitor v(_imp.get());
+ n.accept(v);
+}
+
+GemSpecifications::~GemSpecifications()
+{
+}
+
+GemSpecifications::Iterator
+GemSpecifications::begin() const
+{
+ return Iterator(_imp->specs.begin());
+}
+
+GemSpecifications::Iterator
+GemSpecifications::end() const
+{
+ return Iterator(_imp->specs.end());
+}
+
diff --git a/paludis/repositories/gems/gem_specifications.hh b/paludis/repositories/gems/gem_specifications.hh
new file mode 100644
index 0000000..ec49c76
--- /dev/null
+++ b/paludis/repositories/gems/gem_specifications.hh
@@ -0,0 +1,55 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_GEM_SPECIFICATIONS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_GEM_SPECIFICATIONS_HH 1
+
+#include <paludis/repositories/gems/gem_specification-fwd.hh>
+#include <paludis/repositories/gems/yaml-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/tr1_memory.hh>
+#include <paludis/name-fwd.hh>
+#include <paludis/version_spec-fwd.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace gems
+ {
+ class PALUDIS_VISIBLE GemSpecifications :
+ private PrivateImplementationPattern<GemSpecifications>
+ {
+ public:
+ GemSpecifications(const yaml::Node &);
+ ~GemSpecifications();
+
+ typedef libwrapiter::ForwardIterator<GemSpecifications,
+ const std::pair<const std::pair<QualifiedPackageName, VersionSpec>, tr1::shared_ptr<const GemSpecification> > >
+ Iterator;
+ Iterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ Iterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
+
diff --git a/paludis/repositories/gems/gem_specifications_TEST.cc b/paludis/repositories/gems/gem_specifications_TEST.cc
new file mode 100644
index 0000000..7fe8e8b
--- /dev/null
+++ b/paludis/repositories/gems/gem_specifications_TEST.cc
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_runner.hh>
+#include <test/test_framework.hh>
+#include <paludis/repositories/gems/gem_specification.hh>
+#include <paludis/repositories/gems/yaml.hh>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::gems;
+
+namespace test_cases
+{
+ struct SpecificationsTest : TestCase
+ {
+ SpecificationsTest() : TestCase("gem specifications") { }
+
+ void run()
+ {
+ }
+ } test_specifications;
+}
+
+
diff --git a/paludis/repositories/gems/gems.bash b/paludis/repositories/gems/gems.bash
new file mode 100755
index 0000000..c5e9d80
--- /dev/null
+++ b/paludis/repositories/gems/gems.bash
@@ -0,0 +1,55 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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
+
+unalias -a
+set +C
+unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE
+eval unset LANG ${!LC_*}
+
+if [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] ; then
+ export SANDBOX_WRITE="${SANDBOX_WRITE}/dev/shm:/dev/stdout:/dev/stderr:/dev/null:/dev/tty:/dev/pts"
+ export SANDBOX_WRITE="${SANDBOX_WRITE}:/proc/self/attr:/proc/self/task:/selinux/context"
+ export SANDBOX_ON="1"
+ export SANDBOX_BASHRC="/dev/null"
+ unset BASH_ENV
+fi
+
+shopt -s expand_aliases
+shopt -s extglob
+
+case "${1}" in
+ specification)
+ gem specification "${2}" -v "${3}"
+ exit $?
+ ;;
+
+ install)
+ gem install "${2}" -v "${3}"
+ exit $?
+ ;;
+
+ uninstall)
+ gem uninstall "${2}" -v "${3}" -i -x
+ exit $?
+ ;;
+
+ *)
+ echo "Unknown action ${1}" 1>&2
+ exit 1
+ ;;
+esac
diff --git a/paludis/repositories/gems/gems_repository.cc b/paludis/repositories/gems/gems_repository.cc
new file mode 100644
index 0000000..849d3bf
--- /dev/null
+++ b/paludis/repositories/gems/gems_repository.cc
@@ -0,0 +1,256 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/repositories/gems/gems_repository.hh>
+#include <paludis/repositories/gems/params.hh>
+#include <paludis/repositories/gems/metadata.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/repositories/gems/gem_specification.hh>
+#include <paludis/repositories/gems/gem_specifications.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/system.hh>
+#include <paludis/eapi.hh>
+#include <paludis/hashed_containers.hh>
+#include <fstream>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<GemsRepository>
+ {
+ const gems::RepositoryParams params;
+
+ mutable tr1::shared_ptr<const CategoryNamePartCollection> category_names;
+ mutable MakeHashedMap<CategoryNamePart, tr1::shared_ptr<const QualifiedPackageNameCollection> >::Type package_names;
+ mutable MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<VersionSpecCollection> >::Type versions;
+ mutable MakeHashedMap<std::pair<QualifiedPackageName, VersionSpec>, tr1::shared_ptr<const gems::GemMetadata> >::Type metadata;
+
+ mutable bool has_category_names;
+ mutable bool has_entries;
+
+ Implementation(const gems::RepositoryParams p) :
+ params(p),
+ has_category_names(false),
+ has_entries(false)
+ {
+ }
+ };
+}
+
+GemsRepository::GemsRepository(const gems::RepositoryParams & params) :
+ Repository(RepositoryName("gems"),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(this)
+ .installed_interface(0)
+ .sets_interface(0)
+ .syncable_interface(0)
+ .uninstallable_interface(0)
+ .use_interface(0)
+ .world_interface(0)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .virtuals_interface(0)
+ .provides_interface(0)
+ .contents_interface(0)
+ .config_interface(0)
+ .destination_interface(0)
+ .licenses_interface(0)
+ .portage_interface(0)
+ .pretend_interface(0)
+ .hook_interface(0),
+ "gems"),
+ PrivateImplementationPattern<GemsRepository>(new Implementation<GemsRepository>(params))
+{
+ tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->params.location));
+ config_info->add_kv("buildroot", stringify(_imp->params.buildroot));
+ config_info->add_kv("sync", _imp->params.sync);
+ config_info->add_kv("sync_options", _imp->params.sync_options);
+
+ _info->add_section(config_info);
+}
+
+GemsRepository::~GemsRepository()
+{
+}
+
+void
+GemsRepository::invalidate()
+{
+ _imp.reset(new Implementation<GemsRepository>(_imp->params));
+}
+
+bool
+GemsRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ need_category_names();
+ return _imp->category_names->end() != _imp->category_names->find(c);
+}
+
+bool
+GemsRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ if (! do_has_category_named(q.category))
+ return false;
+
+ need_entries();
+ return _imp->package_names.find(q.category)->second->end() != _imp->package_names.find(q.category)->second->find(q);
+}
+
+tr1::shared_ptr<const CategoryNamePartCollection>
+GemsRepository::do_category_names() const
+{
+ need_category_names();
+ return _imp->category_names;
+}
+
+tr1::shared_ptr<const QualifiedPackageNameCollection>
+GemsRepository::do_package_names(const CategoryNamePart & c) const
+{
+ if (! has_category_named(c))
+ return make_shared_ptr(new QualifiedPackageNameCollection::Concrete);
+
+ need_entries();
+
+ MakeHashedMap<CategoryNamePart, tr1::shared_ptr<const QualifiedPackageNameCollection> >::Type::const_iterator i(
+ _imp->package_names.find(c));
+ if (i == _imp->package_names.end())
+ return make_shared_ptr(new QualifiedPackageNameCollection::Concrete);
+ return i->second;
+}
+
+tr1::shared_ptr<const VersionSpecCollection>
+GemsRepository::do_version_specs(const QualifiedPackageName & q) const
+{
+ if (! has_package_named(q))
+ return make_shared_ptr(new VersionSpecCollection::Concrete);
+
+ need_entries();
+
+ MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<VersionSpecCollection> >::Type::const_iterator i(
+ _imp->versions.find(q));
+ if (_imp->versions.end() == i)
+ return make_shared_ptr(new VersionSpecCollection::Concrete);
+
+ return i->second;
+}
+
+bool
+GemsRepository::do_has_version(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_package_named(q))
+ return false;
+
+ need_entries();
+
+ MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<VersionSpecCollection> >::Type::const_iterator i(
+ _imp->versions.find(q));
+ return i->second->end() != i->second->find(v);
+}
+
+tr1::shared_ptr<const VersionMetadata>
+GemsRepository::do_version_metadata(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ return _imp->metadata.find(std::make_pair(q, v))->second;
+}
+
+void
+GemsRepository::need_category_names() const
+{
+ if (_imp->has_category_names)
+ return;
+
+ tr1::shared_ptr<CategoryNamePartCollection::Concrete> cat(new CategoryNamePartCollection::Concrete);
+ _imp->category_names = cat;
+
+ cat->insert(CategoryNamePart("gems"));
+ _imp->has_category_names = true;
+}
+
+void
+GemsRepository::need_entries() const
+{
+ if (_imp->has_entries)
+ return;
+
+ need_category_names();
+
+ tr1::shared_ptr<QualifiedPackageNameCollection::Concrete> pkgs(new QualifiedPackageNameCollection::Concrete);
+ _imp->package_names.insert(std::make_pair(CategoryNamePart("gems"), pkgs));
+
+ Context context("When loading gems yaml file:");
+
+ std::ifstream yaml_file(stringify(_imp->params.location / "yaml").c_str());
+ if (! yaml_file)
+ throw ConfigurationError("Gems yaml file '" + stringify(_imp->params.location / "yaml") + "' not readable");
+
+ std::string output((std::istreambuf_iterator<char>(yaml_file)), std::istreambuf_iterator<char>());
+ yaml::Document master_doc(output);
+ gems::GemSpecifications specs(*master_doc.top());
+
+ for (gems::GemSpecifications::Iterator i(specs.begin()), i_end(specs.end()) ;
+ i != i_end ; ++i)
+ {
+ pkgs->insert(i->first.first);
+
+ MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<VersionSpecCollection> >::Type::iterator v(_imp->versions.find(i->first.first));
+ if (_imp->versions.end() == v)
+ v = _imp->versions.insert(std::make_pair(i->first.first, make_shared_ptr(new VersionSpecCollection::Concrete))).first;
+
+ v->second->insert(i->first.second);
+
+ tr1::shared_ptr<gems::GemMetadata> m(new gems::GemMetadata(i->first.second));
+ m->populate_from_specification(*i->second);
+ m->eapi = EAPIData::get_instance()->eapi_from_string("gems-1");
+ _imp->metadata.insert(std::make_pair(i->first, m));
+ }
+
+ _imp->has_entries = true;
+}
+
+void
+GemsRepository::do_install(const QualifiedPackageName & q, const VersionSpec & v,
+ const InstallOptions & o) const
+{
+ if (o.fetch_only)
+ return;
+
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ Command cmd(getenv_with_default("PALUDIS_GEMS_DIR", LIBEXECDIR "/paludis") +
+ "/gems/gems.bash install '" + stringify(q.package) + "' '" + stringify(v) + "'");
+ cmd.with_stderr_prefix(stringify(q) + "-" + stringify(v) + "::" + stringify(name()) + "> ");
+ cmd.with_setenv("GEMCACHE", stringify(_imp->params.location / "yaml"));
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Install of '" + stringify(PackageDatabaseEntry(q, v, name())) + "' failed");
+}
+
diff --git a/paludis/repositories/gems/gems_repository.hh b/paludis/repositories/gems/gems_repository.hh
new file mode 100644
index 0000000..edd959e
--- /dev/null
+++ b/paludis/repositories/gems/gems_repository.hh
@@ -0,0 +1,79 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_GEMS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_GEMS_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/repositories/gems/params-fwd.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE GemsRepository :
+ public Repository,
+ public RepositoryInstallableInterface,
+ private PrivateImplementationPattern<GemsRepository>
+ {
+ private:
+ void need_category_names() const;
+ void need_entries() const;
+
+ protected:
+ /* core */
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ /* installable */
+
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ GemsRepository(const gems::RepositoryParams &);
+
+ /**
+ * Destructor.
+ */
+ ~GemsRepository();
+
+ virtual void invalidate();
+ };
+}
+
+#endif
diff --git a/paludis/repositories/gems/gems_repository_TEST.cc b/paludis/repositories/gems/gems_repository_TEST.cc
new file mode 100644
index 0000000..bdff0fe
--- /dev/null
+++ b/paludis/repositories/gems/gems_repository_TEST.cc
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/environments/test/test_environment.hh>
+#include <paludis/repositories/gems/gems_repository.hh>
+#include <paludis/repositories/gems/params.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct CreationTest : TestCase
+ {
+ CreationTest() : TestCase("creation") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ env.package_database()->add_repository(1, make_shared_ptr(new GemsRepository(
+ gems::RepositoryParams::create()
+ .location(FSEntry("gems_repository_TEST_dir/repo"))
+ .sync("")
+ .sync_options("")
+ .environment(&env)
+ .buildroot(FSEntry("gems_repository_TEST_dir/build"))
+ )));
+ }
+ } test_creation;
+}
+
diff --git a/paludis/repositories/gems/gems_repository_TEST_cleanup.sh b/paludis/repositories/gems/gems_repository_TEST_cleanup.sh
new file mode 100755
index 0000000..5d20e5c
--- /dev/null
+++ b/paludis/repositories/gems/gems_repository_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d gems_repository_TEST_dir ] ; then
+ rm -fr gems_repository_TEST_dir
+else
+ true
+fi
+
diff --git a/paludis/repositories/gems/gems_repository_TEST_setup.sh b/paludis/repositories/gems/gems_repository_TEST_setup.sh
new file mode 100755
index 0000000..bbe7b98
--- /dev/null
+++ b/paludis/repositories/gems/gems_repository_TEST_setup.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir gems_repository_TEST_dir || exit 1
+cd gems_repository_TEST_dir || exit 1
+
diff --git a/paludis/repositories/gems/installed_gems_repository.cc b/paludis/repositories/gems/installed_gems_repository.cc
new file mode 100644
index 0000000..e5d4535
--- /dev/null
+++ b/paludis/repositories/gems/installed_gems_repository.cc
@@ -0,0 +1,319 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/repositories/gems/installed_gems_repository.hh>
+#include <paludis/repositories/gems/params.hh>
+#include <paludis/repositories/gems/metadata.hh>
+#include <paludis/repositories/gems/gem_specification.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/package_database.hh>
+#include <paludis/environment.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/eapi.hh>
+
+using namespace paludis;
+
+typedef MakeHashedMap<std::pair<QualifiedPackageName, VersionSpec>, tr1::shared_ptr<const gems::InstalledGemMetadata> >::Type MetadataMap;
+typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<VersionSpecCollection> >::Type VersionsMap;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<InstalledGemsRepository>
+ {
+ const gems::InstalledRepositoryParams params;
+
+ mutable tr1::shared_ptr<const CategoryNamePartCollection> category_names;
+ mutable MakeHashedMap<CategoryNamePart, tr1::shared_ptr<const QualifiedPackageNameCollection> >::Type package_names;
+ mutable VersionsMap versions;
+ mutable MetadataMap metadata;
+
+ mutable bool has_category_names;
+ mutable bool has_entries;
+
+ Implementation(const gems::InstalledRepositoryParams p) :
+ params(p),
+ has_category_names(false),
+ has_entries(false)
+ {
+ }
+ };
+}
+
+InstalledGemsRepository::InstalledGemsRepository(const gems::InstalledRepositoryParams & params) :
+ Repository(RepositoryName("installed-gems"),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(0)
+ .installed_interface(this)
+ .sets_interface(0)
+ .syncable_interface(0)
+ .uninstallable_interface(this)
+ .use_interface(0)
+ .world_interface(0)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .virtuals_interface(0)
+ .provides_interface(0)
+ .contents_interface(0)
+ .config_interface(0)
+ .destination_interface(this)
+ .licenses_interface(0)
+ .portage_interface(0)
+ .pretend_interface(0)
+ .hook_interface(0),
+ "installed_gems"),
+ PrivateImplementationPattern<InstalledGemsRepository>(new Implementation<InstalledGemsRepository>(params))
+{
+ tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->params.location));
+ config_info->add_kv("buildroot", stringify(_imp->params.buildroot));
+
+ _info->add_section(config_info);
+}
+
+InstalledGemsRepository::~InstalledGemsRepository()
+{
+}
+
+void
+InstalledGemsRepository::invalidate()
+{
+ _imp.reset(new Implementation<InstalledGemsRepository>(_imp->params));
+}
+
+bool
+InstalledGemsRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ need_category_names();
+ return _imp->category_names->end() != _imp->category_names->find(c);
+}
+
+bool
+InstalledGemsRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ if (! do_has_category_named(q.category))
+ return false;
+
+ need_entries();
+ return _imp->package_names.find(q.category)->second->end() != _imp->package_names.find(q.category)->second->find(q);
+}
+
+tr1::shared_ptr<const CategoryNamePartCollection>
+InstalledGemsRepository::do_category_names() const
+{
+ need_category_names();
+ return _imp->category_names;
+}
+
+tr1::shared_ptr<const QualifiedPackageNameCollection>
+InstalledGemsRepository::do_package_names(const CategoryNamePart & c) const
+{
+ if (! has_category_named(c))
+ return make_shared_ptr(new QualifiedPackageNameCollection::Concrete);
+
+ need_entries();
+
+ MakeHashedMap<CategoryNamePart, tr1::shared_ptr<const QualifiedPackageNameCollection> >::Type::const_iterator i(
+ _imp->package_names.find(c));
+ if (i == _imp->package_names.end())
+ return make_shared_ptr(new QualifiedPackageNameCollection::Concrete);
+ return i->second;
+}
+
+tr1::shared_ptr<const VersionSpecCollection>
+InstalledGemsRepository::do_version_specs(const QualifiedPackageName & q) const
+{
+ if (! has_package_named(q))
+ return make_shared_ptr(new VersionSpecCollection::Concrete);
+
+ need_entries();
+
+ VersionsMap::const_iterator i(_imp->versions.find(q));
+ if (_imp->versions.end() == i)
+ return make_shared_ptr(new VersionSpecCollection::Concrete);
+
+ return i->second;
+}
+
+bool
+InstalledGemsRepository::do_has_version(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_package_named(q))
+ return false;
+
+ need_entries();
+
+ VersionsMap::const_iterator i(_imp->versions.find(q));
+ return i->second->end() != i->second->find(v);
+}
+
+tr1::shared_ptr<const VersionMetadata>
+InstalledGemsRepository::do_version_metadata(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ need_version_metadata(q, v);
+ return _imp->metadata.find(std::make_pair(q, v))->second;
+}
+
+void
+InstalledGemsRepository::need_category_names() const
+{
+ if (_imp->has_category_names)
+ return;
+
+ tr1::shared_ptr<CategoryNamePartCollection::Concrete> cat(new CategoryNamePartCollection::Concrete);
+ _imp->category_names = cat;
+
+ cat->insert(CategoryNamePart("gems"));
+ _imp->has_category_names = true;
+}
+
+void
+InstalledGemsRepository::need_entries() const
+{
+ if (_imp->has_entries)
+ return;
+
+ static CategoryNamePart gems("gems");
+
+ Context c("When loading entries for repository '" + stringify(name()) + "':");
+
+ need_category_names();
+
+ tr1::shared_ptr<QualifiedPackageNameCollection::Concrete> pkgs(new QualifiedPackageNameCollection::Concrete);
+ _imp->package_names.insert(std::make_pair(gems, pkgs));
+
+ for (DirIterator d(_imp->params.location / "specifications"), d_end ; d != d_end ; ++d)
+ {
+ if (! is_file_with_extension(*d, ".gemspec", IsFileWithOptions()))
+ continue;
+
+ std::string s(strip_trailing_string(d->basename(), ".gemspec"));
+ std::string::size_type h(s.rfind('-'));
+ if (std::string::npos == h)
+ {
+ Log::get_instance()->message(ll_qa, lc_context) << "Unrecognised file name format '"
+ << *d << "' (no hyphen)";
+ continue;
+ }
+
+ VersionSpec v(s.substr(h + 1));
+ PackageNamePart p(s.substr(0, h));
+ pkgs->insert(gems + p);
+
+ if (_imp->versions.end() == _imp->versions.find(gems + p))
+ _imp->versions.insert(std::make_pair(gems + p, make_shared_ptr(new VersionSpecCollection::Concrete)));
+ _imp->versions.find(gems + p)->second->insert(v);
+ }
+}
+
+void
+InstalledGemsRepository::need_version_metadata(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ MetadataMap::const_iterator i(_imp->metadata.find(std::make_pair(q, v)));
+ if (_imp->metadata.end() != i)
+ return;
+
+ Context c("When loading version metadata for '" + stringify(PackageDatabaseEntry(q, v, name())) + "':");
+
+ tr1::shared_ptr<gems::InstalledGemMetadata> m(new gems::InstalledGemMetadata(v));
+ _imp->metadata.insert(std::make_pair(std::make_pair(q, v), m));
+
+ Command cmd(getenv_with_default("PALUDIS_GEMS_DIR", LIBEXECDIR "/paludis") +
+ "/gems/gems.bash specification '" + stringify(q.package) + "' '" + stringify(v) + "'");
+ cmd.with_stderr_prefix(stringify(q) + "-" + stringify(v) + "::" + stringify(name()) + "> ");
+ cmd.with_sandbox();
+ cmd.with_uid_gid(_imp->params.environment->reduced_uid(), _imp->params.environment->reduced_gid());
+
+ PStream p(cmd);
+ std::string output((std::istreambuf_iterator<char>(p)), std::istreambuf_iterator<char>());
+
+ if (0 != p.exit_status())
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Version metadata extraction returned non-zero";
+ return;
+ }
+
+ yaml::Document spec_doc(output);
+ gems::GemSpecification spec(*spec_doc.top());
+ m->populate_from_specification(spec);
+ m->eapi = EAPIData::get_instance()->eapi_from_string("gems-1");
+}
+
+bool
+InstalledGemsRepository::is_suitable_destination_for(const PackageDatabaseEntry & e) const
+{
+ std::string f(_imp->params.environment->package_database()->fetch_repository(e.repository)->format());
+ return f == "gems";
+}
+
+bool
+InstalledGemsRepository::is_default_destination() const
+{
+ return true;
+}
+
+bool
+InstalledGemsRepository::want_pre_post_phases() const
+{
+ return true;
+}
+
+void
+InstalledGemsRepository::merge(const MergeOptions &)
+{
+ throw InternalError(PALUDIS_HERE, "Invalid target for merge");
+}
+
+FSEntry
+InstalledGemsRepository::root() const
+{
+ return FSEntry("/");
+}
+
+void
+InstalledGemsRepository::do_uninstall(const QualifiedPackageName & q, const VersionSpec & v,
+ const UninstallOptions &) const
+{
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ Command cmd(getenv_with_default("PALUDIS_GEMS_DIR", LIBEXECDIR "/paludis") +
+ "/gems/gems.bash uninstall '" + stringify(q.package) + "' '" + stringify(v) + "'");
+ cmd.with_stderr_prefix(stringify(q) + "-" + stringify(v) + "::" + stringify(name()) + "> ");
+ cmd.with_setenv("GEMCACHE", stringify(_imp->params.location / "yaml"));
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Uninstall of '" + stringify(PackageDatabaseEntry(q, v, name())) + "' failed");
+}
+
diff --git a/paludis/repositories/gems/installed_gems_repository.hh b/paludis/repositories/gems/installed_gems_repository.hh
new file mode 100644
index 0000000..93e743c
--- /dev/null
+++ b/paludis/repositories/gems/installed_gems_repository.hh
@@ -0,0 +1,94 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_INSTALLED_GEMS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_INSTALLED_GEMS_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/repositories/gems/params-fwd.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE InstalledGemsRepository :
+ public Repository,
+ public RepositoryDestinationInterface,
+ public RepositoryInstalledInterface,
+ public RepositoryUninstallableInterface,
+ private PrivateImplementationPattern<InstalledGemsRepository>
+ {
+ private:
+ void need_category_names() const;
+ void need_entries() const;
+ void need_version_metadata(const QualifiedPackageName &, const VersionSpec &) const;
+
+ protected:
+ /* core */
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ /* uninstallable */
+
+ virtual void do_uninstall(const QualifiedPackageName &, const VersionSpec &,
+ const UninstallOptions &) const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ InstalledGemsRepository(const gems::InstalledRepositoryParams &);
+
+ /**
+ * Destructor.
+ */
+ ~InstalledGemsRepository();
+
+ virtual void invalidate();
+
+ /* destination */
+
+ virtual bool is_suitable_destination_for(const PackageDatabaseEntry &) const;
+ virtual bool is_default_destination() const;
+ virtual bool want_pre_post_phases() const;
+ virtual void merge(const MergeOptions &) PALUDIS_ATTRIBUTE((noreturn));
+
+ /* installed */
+ virtual FSEntry root() const;
+
+ };
+}
+
+
+#endif
diff --git a/paludis/repositories/gems/installed_gems_repository_TEST.cc b/paludis/repositories/gems/installed_gems_repository_TEST.cc
new file mode 100644
index 0000000..54be5f4
--- /dev/null
+++ b/paludis/repositories/gems/installed_gems_repository_TEST.cc
@@ -0,0 +1,49 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/environments/test/test_environment.hh>
+#include <paludis/repositories/gems/gems_repository.hh>
+#include <paludis/repositories/gems/params.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct CreationTest : TestCase
+ {
+ CreationTest() : TestCase("creation") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ env.package_database()->add_repository(1, make_shared_ptr(new InstalledGemsRepository(
+ gems::InstalledRepositoryParams::create()
+ .location(FSEntry("gems_repository_TEST_dir/installed-repo"))
+ .environment(&env)
+ .buildroot(FSEntry("gems_repository_TEST_dir/build"))
+ )));
+ }
+ } test_creation;
+}
+
diff --git a/paludis/repositories/gems/installed_gems_repository_TEST_cleanup.sh b/paludis/repositories/gems/installed_gems_repository_TEST_cleanup.sh
new file mode 100755
index 0000000..2d8baec
--- /dev/null
+++ b/paludis/repositories/gems/installed_gems_repository_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d installed_gems_repository_TEST_dir ] ; then
+ rm -fr installed_gems_repository_TEST_dir
+else
+ true
+fi
+
diff --git a/paludis/repositories/gems/installed_gems_repository_TEST_setup.sh b/paludis/repositories/gems/installed_gems_repository_TEST_setup.sh
new file mode 100755
index 0000000..36e4acf
--- /dev/null
+++ b/paludis/repositories/gems/installed_gems_repository_TEST_setup.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir installed_gems_repository_TEST_dir || exit 1
+cd installed_gems_repository_TEST_dir || exit 1
+
diff --git a/paludis/repositories/gems/metadata.cc b/paludis/repositories/gems/metadata.cc
new file mode 100644
index 0000000..46c5a40
--- /dev/null
+++ b/paludis/repositories/gems/metadata.cc
@@ -0,0 +1,87 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/repositories/gems/metadata.hh>
+#include <paludis/repositories/gems/gem_specification.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/eapi.hh>
+
+using namespace paludis;
+using namespace paludis::gems;
+
+InstalledGemMetadata::InstalledGemMetadata(const VersionSpec & v) :
+ VersionMetadata(
+ VersionMetadataBase::create()
+ .slot(SlotName(stringify(v)))
+ .homepage("")
+ .description("")
+ .eapi(EAPIData::get_instance()->unknown_eapi())
+ .interactive(false),
+ VersionMetadataCapabilities::create()
+ .ebuild_interface(0)
+ .cran_interface(0)
+ .deps_interface(0)
+ .license_interface(0)
+ .virtual_interface(0)
+ .origins_interface(0)
+ .ebin_interface(0))
+{
+}
+
+InstalledGemMetadata::~InstalledGemMetadata()
+{
+}
+
+void
+InstalledGemMetadata::populate_from_specification(const GemSpecification & spec)
+{
+ description = spec.summary();
+ set_homepage(spec.homepage());
+}
+
+GemMetadata::GemMetadata(const VersionSpec & v) :
+ VersionMetadata(
+ VersionMetadataBase::create()
+ .slot(SlotName(stringify(v)))
+ .homepage("")
+ .description("")
+ .eapi(EAPIData::get_instance()->unknown_eapi())
+ .interactive(false),
+ VersionMetadataCapabilities::create()
+ .ebuild_interface(0)
+ .cran_interface(0)
+ .deps_interface(0)
+ .license_interface(0)
+ .virtual_interface(0)
+ .origins_interface(0)
+ .ebin_interface(0))
+{
+}
+
+GemMetadata::~GemMetadata()
+{
+}
+
+void
+GemMetadata::populate_from_specification(const GemSpecification & spec)
+{
+ description = spec.summary();
+ set_homepage(spec.homepage());
+}
+
diff --git a/paludis/repositories/gems/metadata.hh b/paludis/repositories/gems/metadata.hh
new file mode 100644
index 0000000..159d0f5
--- /dev/null
+++ b/paludis/repositories/gems/metadata.hh
@@ -0,0 +1,66 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_METADATA_HH 1
+
+#include <paludis/version_metadata.hh>
+#include <paludis/version_spec-fwd.hh>
+#include <paludis/repositories/gems/gem_specification-fwd.hh>
+
+namespace paludis
+{
+ namespace gems
+ {
+ class GemMetadata :
+ public VersionMetadata,
+ public virtual VersionMetadataHasInterfaces
+ {
+ public:
+ GemMetadata(const VersionSpec &);
+ virtual ~GemMetadata();
+
+ virtual const VersionMetadata * version_metadata() const
+ {
+ return this;
+ }
+
+ void populate_from_specification(const GemSpecification &);
+ };
+
+ class InstalledGemMetadata :
+ public VersionMetadata,
+ public VersionMetadataOriginsInterface,
+ public virtual VersionMetadataHasInterfaces
+ {
+ public:
+ InstalledGemMetadata(const VersionSpec &);
+ virtual ~InstalledGemMetadata();
+
+ virtual const VersionMetadata * version_metadata() const
+ {
+ return this;
+ }
+
+ void populate_from_specification(const GemSpecification &);
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/params-fwd.hh b/paludis/repositories/gems/params-fwd.hh
new file mode 100644
index 0000000..d84c6e2
--- /dev/null
+++ b/paludis/repositories/gems/params-fwd.hh
@@ -0,0 +1,32 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_PARAMS_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_PARAMS_FWD_HH 1
+
+namespace paludis
+{
+ namespace gems
+ {
+ class RepositoryParams;
+ class InstalledRepositoryParams;
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/params.cc b/paludis/repositories/gems/params.cc
new file mode 100644
index 0000000..8f13f9a
--- /dev/null
+++ b/paludis/repositories/gems/params.cc
@@ -0,0 +1,26 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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 "params.hh"
+
+using namespace paludis;
+using namespace paludis::gems;
+
+#include <paludis/repositories/gems/params-sr.cc>
+
diff --git a/paludis/repositories/gems/params.hh b/paludis/repositories/gems/params.hh
new file mode 100644
index 0000000..36956a9
--- /dev/null
+++ b/paludis/repositories/gems/params.hh
@@ -0,0 +1,41 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_PARAMS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_PARAMS_HH 1
+
+#include <paludis/repositories/gems/params-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/sr.hh>
+#include <string>
+
+namespace paludis
+{
+ class Environment;
+
+ namespace gems
+ {
+
+#include <paludis/repositories/gems/params-sr.hh>
+
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/params.sr b/paludis/repositories/gems/params.sr
new file mode 100644
index 0000000..47f7eeb
--- /dev/null
+++ b/paludis/repositories/gems/params.sr
@@ -0,0 +1,27 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_RepositoryParams()
+{
+ visible
+
+ key environment "Environment *"
+ key location FSEntry
+ key sync std::string
+ key sync_options std::string
+ key buildroot FSEntry
+
+ allow_named_args
+}
+
+make_class_InstalledRepositoryParams()
+{
+ visible
+
+ key environment "Environment *"
+ key location FSEntry
+ key buildroot FSEntry
+
+ allow_named_args
+}
+
diff --git a/paludis/repositories/gems/registration.cc b/paludis/repositories/gems/registration.cc
new file mode 100644
index 0000000..18f1a32
--- /dev/null
+++ b/paludis/repositories/gems/registration.cc
@@ -0,0 +1,91 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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/repositories/repository_maker.hh>
+#include <paludis/repositories/gems/gems_repository.hh>
+#include <paludis/repositories/gems/installed_gems_repository.hh>
+#include <paludis/repositories/gems/params.hh>
+#include <paludis/repositories/gems/exceptions.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/distribution.hh>
+
+using namespace paludis;
+
+namespace
+{
+ tr1::shared_ptr<Repository>
+ make_gems_repository(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+ {
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw gems::RepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string sync;
+ if (m->end() != m->find("sync"))
+ sync = m->find("sync")->second;
+
+ std::string sync_options;
+ if (m->end() != m->find("sync_options"))
+ sync_options = m->find("sync_options")->second;
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = DistributionData::get_instance()->default_distribution()->default_ebuild_build_root;
+
+ return make_shared_ptr(new GemsRepository(gems::RepositoryParams::create()
+ .location(location)
+ .sync(sync)
+ .sync_options(sync_options)
+ .environment(env)
+ .buildroot(buildroot)));
+ }
+
+ tr1::shared_ptr<Repository>
+ make_installed_gems_repository(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+ {
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw gems::RepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = DistributionData::get_instance()->default_distribution()->default_ebuild_build_root;
+
+ return make_shared_ptr(new InstalledGemsRepository(gems::InstalledRepositoryParams::create()
+ .location(location)
+ .environment(env)
+ .buildroot(buildroot)));
+ }
+}
+
+extern "C"
+{
+ void PALUDIS_VISIBLE register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("gems", &make_gems_repository);
+ maker->register_maker("installed_gems", &make_installed_gems_repository);
+}
+
diff --git a/paludis/repositories/gems/yaml-fwd.hh b/paludis/repositories/gems/yaml-fwd.hh
new file mode 100644
index 0000000..59a80b1
--- /dev/null
+++ b/paludis/repositories/gems/yaml-fwd.hh
@@ -0,0 +1,38 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_YAML_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_YAML_FWD_HH 1
+
+namespace paludis
+{
+ namespace yaml
+ {
+ class Node;
+ class StringNode;
+ class SequenceNode;
+ class MapNode;
+ class NodeVisitorTypes;
+ class Document;
+ class NodeManager;
+ class ParseError;
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/yaml.cc b/paludis/repositories/gems/yaml.cc
new file mode 100644
index 0000000..82563b2
--- /dev/null
+++ b/paludis/repositories/gems/yaml.cc
@@ -0,0 +1,364 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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 "yaml.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <syck.h>
+#include <cstring>
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::yaml;
+
+Node::~Node()
+{
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<StringNode>
+ {
+ const std::string text;
+
+ Implementation(const std::string & t) :
+ text(t)
+ {
+ }
+ };
+}
+
+StringNode::StringNode(const std::string & t) :
+ PrivateImplementationPattern<StringNode>(new Implementation<StringNode>(t))
+{
+}
+
+StringNode::~StringNode()
+{
+}
+
+std::string
+StringNode::text() const
+{
+ return _imp->text;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<SequenceNode>
+ {
+ std::list<const Node *> nodes;
+ };
+}
+
+SequenceNode::SequenceNode() :
+ PrivateImplementationPattern<SequenceNode>(new Implementation<SequenceNode>)
+{
+}
+
+SequenceNode::~SequenceNode()
+{
+}
+
+void
+SequenceNode::push_back(const Node * const n)
+{
+ _imp->nodes.push_back(n);
+}
+
+SequenceNode::Iterator
+SequenceNode::begin() const
+{
+ return Iterator(_imp->nodes.begin());
+}
+
+SequenceNode::Iterator
+SequenceNode::end() const
+{
+ return Iterator(_imp->nodes.end());
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<MapNode>
+ {
+ std::list<std::pair<const Node *, const Node *> > nodes;
+ };
+}
+
+MapNode::MapNode() :
+ PrivateImplementationPattern<MapNode>(new Implementation<MapNode>)
+{
+}
+
+MapNode::~MapNode()
+{
+}
+
+void
+MapNode::push_back(const std::pair<const Node *, const Node *> & p)
+{
+ _imp->nodes.push_back(p);
+}
+
+MapNode::Iterator
+MapNode::begin() const
+{
+ return Iterator(_imp->nodes.begin());
+}
+
+MapNode::Iterator
+MapNode::end() const
+{
+ return Iterator(_imp->nodes.end());
+}
+
+namespace
+{
+ struct MatchStringVisitor :
+ ConstVisitor<NodeVisitorTypes>
+ {
+ bool found;
+ const std::string target;
+
+ MatchStringVisitor(const std::string & s) :
+ found(false),
+ target(s)
+ {
+ }
+
+ void visit(const StringNode & n)
+ {
+ found = n.text() == target;
+ }
+
+ void visit(const MapNode &)
+ {
+ }
+
+ void visit(const SequenceNode &)
+ {
+ }
+ };
+
+ bool match_string_node(const std::string & s, const Node * const n)
+ {
+ MatchStringVisitor v(s);
+ n->accept(v);
+ return v.found;
+ }
+}
+
+MapNode::Iterator
+MapNode::find(const std::string & s) const
+{
+ using namespace tr1::placeholders;
+ return std::find_if(begin(), end(),
+ tr1::bind(match_string_node, s, tr1::bind<const Node *>(tr1::mem_fn(&std::pair<const Node *, const Node *>::first), _1)));
+}
+
+namespace
+{
+ static std::map<void *, std::string> document_error_table;
+
+ template <typename R_, typename T_>
+ struct CallUnlessNull
+ {
+ R_ (* function) (T_ *);
+
+ CallUnlessNull(R_ (*f) (T_ *)) :
+ function(f)
+ {
+ }
+
+ void operator() (T_ * const t) const
+ {
+ if (t)
+ function(t);
+ }
+ };
+
+ template <typename R_, typename T_>
+ CallUnlessNull<R_, T_>
+ call_unless_null(R_ (* f) (T_ *))
+ {
+ return CallUnlessNull<R_, T_>(f);
+ }
+
+ SYMID node_handler(SyckParser * p, SyckNode * n)
+ {
+ Node * node(0);
+
+ switch (n->kind)
+ {
+ case syck_str_kind:
+ {
+ node = new StringNode(std::string(n->data.str->ptr, n->data.str->len));
+ NodeManager::get_instance()->manage_node(p, node);
+ }
+ break;
+
+ case syck_seq_kind:
+ {
+ SequenceNode * s(new SequenceNode);
+ NodeManager::get_instance()->manage_node(p, s);
+ for (int i = 0 ; i < n->data.list->idx ; ++i)
+ {
+ SYMID v_id(syck_seq_read(n, i));
+ char * v(0);
+ syck_lookup_sym(p, v_id, &v);
+ s->push_back(reinterpret_cast<Node *>(v));
+ }
+ node = s;
+ }
+ break;
+
+ case syck_map_kind:
+ {
+ MapNode * m(new MapNode);
+ NodeManager::get_instance()->manage_node(p, m);
+ for (int i = 0 ; i < n->data.pairs->idx ; ++i)
+ {
+ SYMID k_id(syck_map_read(n, map_key, i)), v_id(syck_map_read(n, map_value, i));
+ char * k(0), * v(0);
+ syck_lookup_sym(p, k_id, &k);
+ syck_lookup_sym(p, v_id, &v);
+ m->push_back(std::make_pair(reinterpret_cast<Node *>(k), reinterpret_cast<Node *>(v)));
+ }
+ node = m;
+ }
+ break;
+ }
+
+ return syck_add_sym(p, reinterpret_cast<char *>(node));
+ }
+
+ void error_handler(SyckParser * p, char * s)
+ {
+ document_error_table[p] = s;
+ }
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<Document>
+ {
+ Node * top;
+ tr1::shared_ptr<SyckParser> parser;
+ tr1::shared_ptr<char> data;
+ unsigned data_length;
+
+ Implementation(const std::string & s) :
+ top(0),
+ parser(syck_new_parser(), call_unless_null(syck_free_parser)),
+ data(strdup(s.c_str()), call_unless_null(std::free)),
+ data_length(s.length())
+ {
+ }
+ };
+}
+
+Document::Document(const std::string & s) :
+ PrivateImplementationPattern<Document>(new Implementation<Document>(s))
+{
+ Context c("When parsing yaml document:");
+ NodeManager::get_instance()->register_document(_imp->parser.get());
+
+ syck_parser_str(_imp->parser.get(), _imp->data.get(), _imp->data_length, 0);
+ syck_parser_handler(_imp->parser.get(), node_handler);
+ syck_parser_error_handler(_imp->parser.get(), error_handler);
+
+ SYMID root_id(syck_parse(_imp->parser.get()));
+
+ if (document_error_table.end() != document_error_table.find(_imp->parser.get()))
+ {
+ std::string e(document_error_table.find(_imp->parser.get())->second);
+ document_error_table.erase(_imp->parser.get());
+ throw ParseError(e);
+ }
+
+ char * root_uncasted(0);
+ syck_lookup_sym(_imp->parser.get(), root_id, &root_uncasted);
+ _imp->top = reinterpret_cast<Node *>(root_uncasted);
+}
+
+Document::~Document()
+{
+ NodeManager::get_instance()->deregister_document(_imp->parser.get());
+}
+
+const Node *
+Document::top() const
+{
+ return _imp->top;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<NodeManager>
+ {
+ std::map<const void *, std::list<tr1::shared_ptr<const Node> > > store;
+ };
+}
+
+NodeManager::NodeManager() :
+ PrivateImplementationPattern<NodeManager>(new Implementation<NodeManager>)
+{
+}
+
+NodeManager::~NodeManager()
+{
+}
+
+void
+NodeManager::register_document(const void * const d)
+{
+ if (! _imp->store.insert(std::make_pair(d, std::list<tr1::shared_ptr<const Node> >())).second)
+ throw InternalError(PALUDIS_HERE, "duplicate document");
+}
+
+void
+NodeManager::deregister_document(const void * const d)
+{
+ if (0 == _imp->store.erase(d))
+ throw InternalError(PALUDIS_HERE, "no such document");
+}
+
+void
+NodeManager::manage_node(const void * const d, const Node * const n)
+{
+ std::map<const void *, std::list<tr1::shared_ptr<const Node> > >::iterator i(_imp->store.find(d));
+ if (i == _imp->store.end())
+ throw InternalError(PALUDIS_HERE, "no such document");
+ i->second.push_back(make_shared_ptr(n));
+}
+
+ParseError::ParseError(const std::string & s) throw () :
+ Exception(s)
+{
+}
+
diff --git a/paludis/repositories/gems/yaml.hh b/paludis/repositories/gems/yaml.hh
new file mode 100644
index 0000000..cebc33b
--- /dev/null
+++ b/paludis/repositories/gems/yaml.hh
@@ -0,0 +1,137 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_REPOSITORIES_GEMS_YAML_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_YAML_HH 1
+
+#include <paludis/repositories/gems/yaml-fwd.hh>
+#include <paludis/util/visitor.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/exception.hh>
+
+namespace paludis
+{
+ namespace yaml
+ {
+ class Node;
+ class StringNode;
+ class SequenceNode;
+ class MapNode;
+
+ struct NodeVisitorTypes :
+ VisitorTypes<
+ NodeVisitorTypes,
+ Node,
+ StringNode,
+ SequenceNode,
+ MapNode>
+ {
+ };
+
+ class PALUDIS_VISIBLE Node :
+ public virtual ConstAcceptInterface<NodeVisitorTypes>
+ {
+ public:
+ virtual ~Node() = 0;
+ };
+
+ class PALUDIS_VISIBLE StringNode :
+ public Node,
+ public ConstAcceptInterfaceVisitsThis<NodeVisitorTypes, StringNode>,
+ private PrivateImplementationPattern<StringNode>
+ {
+ public:
+ StringNode(const std::string &);
+ ~StringNode();
+
+ std::string text() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE SequenceNode :
+ public Node,
+ public ConstAcceptInterfaceVisitsThis<NodeVisitorTypes, SequenceNode>,
+ private PrivateImplementationPattern<SequenceNode>
+ {
+ public:
+ SequenceNode();
+ ~SequenceNode();
+
+ void push_back(const Node * const);
+
+ typedef libwrapiter::ForwardIterator<SequenceNode, const Node * const> Iterator;
+ Iterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ Iterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE MapNode :
+ public Node,
+ public ConstAcceptInterfaceVisitsThis<NodeVisitorTypes, MapNode>,
+ private PrivateImplementationPattern<MapNode>
+ {
+ public:
+ MapNode();
+ ~MapNode();
+
+ void push_back(const std::pair<const Node *, const Node *> &);
+
+ typedef libwrapiter::ForwardIterator<MapNode, const std::pair<const Node *, const Node *> > Iterator;
+ Iterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ Iterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ Iterator find(const std::string &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE Document :
+ private PrivateImplementationPattern<Document>
+ {
+ public:
+ Document(const std::string &);
+ ~Document();
+
+ const Node * top() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE NodeManager :
+ private PrivateImplementationPattern<NodeManager>,
+ public InstantiationPolicy<NodeManager, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<NodeManager, instantiation_method::SingletonTag>;
+
+ private:
+ NodeManager();
+ ~NodeManager();
+
+ public:
+ void register_document(const void * const);
+ void deregister_document(const void * const);
+
+ void manage_node(const void * const, const Node * const);
+ };
+
+ class PALUDIS_VISIBLE ParseError :
+ public Exception
+ {
+ public:
+ ParseError(const std::string &) throw ();
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gems/yaml_TEST.cc b/paludis/repositories/gems/yaml_TEST.cc
new file mode 100644
index 0000000..4b4351e
--- /dev/null
+++ b/paludis/repositories/gems/yaml_TEST.cc
@@ -0,0 +1,185 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.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_runner.hh>
+#include <test/test_framework.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <algorithm>
+#include <sstream>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::yaml;
+
+namespace
+{
+ struct CountedStringNode :
+ StringNode
+ {
+ static unsigned alloc_count;
+
+ void * operator new (const std::size_t sz) throw (std::bad_alloc)
+ {
+ ++alloc_count;
+ return ::operator new (sz);
+ }
+
+ void operator delete (void * n) throw ()
+ {
+ --alloc_count;
+ ::operator delete (n);
+ }
+
+ CountedStringNode() :
+ StringNode("x")
+ {
+ }
+ };
+
+ unsigned CountedStringNode::alloc_count(0);
+
+ struct FakeDocument
+ {
+ FakeDocument()
+ {
+ NodeManager::get_instance()->register_document(this);
+ }
+
+ ~FakeDocument()
+ {
+ NodeManager::get_instance()->deregister_document(this);
+ }
+ };
+
+ struct Dumper :
+ ConstVisitor<NodeVisitorTypes>
+ {
+ std::stringstream s;
+
+ void visit(const StringNode & n)
+ {
+ s << "str(" << n.text() << ")";
+ }
+
+ void visit(const MapNode & n)
+ {
+ s << "map(";
+ bool w(false);
+ for (MapNode::Iterator i(n.begin()), i_end(n.end()) ; i != i_end ; ++i)
+ {
+ if (w)
+ s << ", ";
+
+ i->first->accept(*this);
+ s << " -> ";
+ i->second->accept(*this);
+ w = true;
+ }
+ s << ")";
+ }
+
+ void visit(const SequenceNode & n)
+ {
+ s << "seq(";
+ bool w(false);
+ for (SequenceNode::Iterator i(n.begin()), i_end(n.end()) ; i != i_end ; ++i)
+ {
+ if (w)
+ s << ", ";
+ (*i)->accept(*this);
+ w = true;
+ }
+ s << ")";
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct ManagementTest : TestCase
+ {
+ ManagementTest() : TestCase("management") { }
+
+ void run()
+ {
+ TEST_CHECK_EQUAL(CountedStringNode::alloc_count, 0u);
+ {
+ FakeDocument d;
+ NodeManager::get_instance()->manage_node(&d, new CountedStringNode);
+ NodeManager::get_instance()->manage_node(&d, new CountedStringNode);
+ NodeManager::get_instance()->manage_node(&d, new CountedStringNode);
+ TEST_CHECK_EQUAL(CountedStringNode::alloc_count, 3u);
+ }
+ TEST_CHECK_EQUAL(CountedStringNode::alloc_count, 0u);
+ }
+ } test_management;
+
+ struct ParseTest : TestCase
+ {
+ ParseTest() : TestCase("parse") { }
+
+ void run()
+ {
+ Document doc("foo: [ bar, baz ]");
+ TEST_CHECK(doc.top());
+
+ Dumper dumper;
+ doc.top()->accept(dumper);
+ TEST_CHECK_EQUAL(dumper.s.str(), "map(str(foo) -> seq(str(bar), str(baz)))");
+ }
+ } test_parse;
+
+ struct ParseErrorTest : TestCase
+ {
+ ParseErrorTest() : TestCase("parse error") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(Document("foo: [ bar, baz"), ParseError);
+ }
+ } test_parse_error;
+
+ struct MapFindTest : TestCase
+ {
+ MapFindTest() : TestCase("map find") { }
+
+ void run()
+ {
+ Document doc("{ foo: bar, bar: baz, monkey: pants }");
+ TEST_CHECK(doc.top());
+
+ Dumper dumper;
+ doc.top()->accept(dumper);
+ TEST_CHECK_EQUAL(dumper.s.str(), "map(str(foo) -> str(bar), str(bar) -> str(baz), str(monkey) -> str(pants))");
+
+ const MapNode * m(static_cast<const MapNode *>(doc.top()));
+ TEST_CHECK(m->find("foo") != m->end());
+ TEST_CHECK(m->find("bar") != m->end());
+ TEST_CHECK(m->find("monkey") != m->end());
+ TEST_CHECK(m->find("baz") == m->end());
+
+ TEST_CHECK_EQUAL(static_cast<const StringNode *>(m->find("foo")->second)->text(), "bar");
+ TEST_CHECK_EQUAL(static_cast<const StringNode *>(m->find("bar")->second)->text(), "baz");
+ TEST_CHECK_EQUAL(static_cast<const StringNode *>(m->find("monkey")->second)->text(), "pants");
+ }
+ } test_map_find;
+}
+
diff --git a/paludis/repositories/gentoo/traditional_layout.cc b/paludis/repositories/gentoo/traditional_layout.cc
index a68a738..09de664 100644
--- a/paludis/repositories/gentoo/traditional_layout.cc
+++ b/paludis/repositories/gentoo/traditional_layout.cc
@@ -235,7 +235,7 @@ TraditionalLayout::need_category_names_collection() const
_imp->category_names_collection.reset(new CategoryNamePartCollection::Concrete);
std::copy(_imp->category_names.begin(), _imp->category_names.end(),
transform_inserter(_imp->category_names_collection->inserter(),
- SelectFirst<const CategoryNamePart, bool>()));
+ tr1::mem_fn(&std::pair<const CategoryNamePart, bool>::first)));
}
tr1::shared_ptr<const CategoryNamePartCollection>
@@ -291,11 +291,10 @@ TraditionalLayout::package_names(const CategoryNamePart & c) const
tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
- std::copy(_imp->package_names.begin(), _imp->package_names.end(),
- transform_inserter(filter_inserter(result->inserter(),
- tr1::bind(std::equal_to<CategoryNamePart>(), c,
- tr1::bind(SelectMember<const QualifiedPackageName, CategoryNamePart, &QualifiedPackageName::category>(), _1))),
- SelectFirst<const QualifiedPackageName, bool>()));
+ for (PackagesMap::const_iterator p(_imp->package_names.begin()), p_end(_imp->package_names.end()) ;
+ p != p_end ; ++p)
+ if (p->first.category == c)
+ result->insert(p->first);
return result;
}
diff --git a/paludis/repositories/gentoo/vdb_unmerger.cc b/paludis/repositories/gentoo/vdb_unmerger.cc
index daab19e..5c6f755 100644
--- a/paludis/repositories/gentoo/vdb_unmerger.cc
+++ b/paludis/repositories/gentoo/vdb_unmerger.cc
@@ -71,7 +71,7 @@ VDBUnmerger::VDBUnmerger(const VDBUnmergerOptions & o) :
.environment(o.environment)
.root(o.root)),
PrivateImplementationPattern<VDBUnmerger>(new Implementation<VDBUnmerger>(o)),
- _imp(PrivateImplementationPattern<VDBUnmerger>::_imp.operator-> ())
+ _imp(PrivateImplementationPattern<VDBUnmerger>::_imp.get())
{
}
diff --git a/paludis/repositories/virtuals/virtuals_repository.cc b/paludis/repositories/virtuals/virtuals_repository.cc
index 25aaad5..0cc7187 100644
--- a/paludis/repositories/virtuals/virtuals_repository.cc
+++ b/paludis/repositories/virtuals/virtuals_repository.cc
@@ -25,6 +25,7 @@
#include <paludis/util/fast_unique_copy.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/log.hh>
+#include <paludis/util/tr1_functional.hh>
#include <paludis/query.hh>
#include <vector>
#include "vr_entry.hh"
@@ -317,7 +318,7 @@ VirtualsRepository::do_package_names(const CategoryNamePart & c) const
tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
std::copy(p.first, p.second, transform_inserter(result->inserter(),
- SelectFirst<QualifiedPackageName, tr1::shared_ptr<const PackageDepSpec> >()));
+ tr1::mem_fn(&std::pair<QualifiedPackageName, tr1::shared_ptr<const PackageDepSpec> >::first)));
return result;
}
diff --git a/paludis/util/Makefile.am.m4 b/paludis/util/Makefile.am.m4
index 172e255..e43637a 100644
--- a/paludis/util/Makefile.am.m4
+++ b/paludis/util/Makefile.am.m4
@@ -26,7 +26,7 @@ define(`addhh', `define(`filelist', filelist `$1.hh')define(`headerlist', header
define(`addfwd', `define(`filelist', filelist `$1-fwd.hh')define(`headerlist', headerlist `$1-fwd.hh')')dnl
define(`addhhx', `define(`filelist', filelist `$1.hh')')dnl
define(`addcc', `define(`filelist', filelist `$1.cc')')dnl
-define(`addimpl', `define(`filelist', filelist `$1-impl.hh')')dnl
+define(`addimpl', `define(`filelist', filelist `$1-impl.hh')define(`headerlist', headerlist `$1-impl.hh')')dnl
define(`addsr', `define(`srlist', srlist `$1.sr')dnl
define(`srcleanlist', srcleanlist `$1-sr.hh $1-sr.cc')dnl
define(`srheaderlist', srheaderlist `$1-sr.hh')dnl
diff --git a/paludis/util/iterator.hh b/paludis/util/iterator.hh
index 221aeee..4aec97f 100644
--- a/paludis/util/iterator.hh
+++ b/paludis/util/iterator.hh
@@ -407,44 +407,6 @@ namespace paludis
}
/**
- * Convenience class: select a member of a class.
- *
- * \ingroup grpiterators
- */
- template <typename T_, typename M_, M_ T_::* m_>
- struct SelectMember :
- std::unary_function<T_, M_>
- {
- /// Carry out the selection.
- M_ operator() (const T_ & p) const
- {
- return p.*m_;
- }
- };
-
- /**
- * Convenience class: select the first item of a pair.
- *
- * \ingroup grpiterators
- */
- template <typename A_, typename B_>
- struct SelectFirst :
- SelectMember<std::pair<A_, B_>, A_, &std::pair<A_, B_>::first>
- {
- };
-
- /**
- * Convenience class: select the second item of a pair.
- *
- * \ingroup grpiterators
- */
- template <typename A_, typename B_>
- struct SelectSecond :
- SelectMember<std::pair<A_, B_>, B_, &std::pair<A_, B_>::second>
- {
- };
-
- /**
* A CreateInsertIterator is an insert iterator that creates an object of
* the specified type using the provided value.
*
diff --git a/paludis/util/iterator_TEST.cc b/paludis/util/iterator_TEST.cc
index 8a2cb76..bd6e06a 100644
--- a/paludis/util/iterator_TEST.cc
+++ b/paludis/util/iterator_TEST.cc
@@ -294,25 +294,6 @@ namespace test_cases
}
}
} test_transform_insert_iterator;
-
- /**
- * \test Test SelectFirst and SelectSecond.
- *
- */
- struct SimpleSelectPairTest : TestCase
- {
- SimpleSelectPairTest() : TestCase("Simple SelectFirst and SelectSecond") {}
-
- void run()
- {
- std::pair<int, int> p(1,2);
- SelectFirst<int, int> f;
- SelectSecond<int, int> s;
-
- TEST_CHECK(f(p) == 1);
- TEST_CHECK(s(p) == 2);
- }
- } test_select_pair;
}
#ifndef DOXYGEN
diff --git a/paludis/util/options.cc b/paludis/util/options.cc
index 51e6501..ccf90a0 100644
--- a/paludis/util/options.cc
+++ b/paludis/util/options.cc
@@ -50,7 +50,7 @@ OptionsStore::OptionsStore() :
}
OptionsStore::OptionsStore(const OptionsStore & s) :
- PrivateImplementationPattern<OptionsStore>(new Implementation<OptionsStore>(*s._imp.operator-> ()))
+ PrivateImplementationPattern<OptionsStore>(new Implementation<OptionsStore>(*s._imp.get()))
{
}
@@ -58,7 +58,7 @@ const OptionsStore &
OptionsStore::operator= (const OptionsStore & s)
{
if (this != &s)
- _imp.reset(new Implementation<OptionsStore>(*s._imp.operator-> ()));
+ _imp.reset(new Implementation<OptionsStore>(*s._imp.get()));
return *this;
}
diff --git a/paludis/util/private_implementation_pattern-impl.hh b/paludis/util/private_implementation_pattern-impl.hh
index 83a9967..a16223d 100644
--- a/paludis/util/private_implementation_pattern-impl.hh
+++ b/paludis/util/private_implementation_pattern-impl.hh
@@ -49,6 +49,20 @@ paludis::PrivateImplementationPattern<C_>::ImpPtr::operator-> () const
}
template <typename C_>
+paludis::Implementation<C_> *
+paludis::PrivateImplementationPattern<C_>::ImpPtr::get()
+{
+ return _ptr;
+}
+
+template <typename C_>
+const paludis::Implementation<C_> *
+paludis::PrivateImplementationPattern<C_>::ImpPtr::get() const
+{
+ return _ptr;
+}
+
+template <typename C_>
void
paludis::PrivateImplementationPattern<C_>::ImpPtr::reset(Implementation<C_> * p)
{
diff --git a/paludis/util/private_implementation_pattern.hh b/paludis/util/private_implementation_pattern.hh
index 65b9bf6..42f1a50 100644
--- a/paludis/util/private_implementation_pattern.hh
+++ b/paludis/util/private_implementation_pattern.hh
@@ -80,6 +80,9 @@ namespace paludis
const Implementation<C_> * operator-> () const;
+ Implementation<C_> * get();
+ const Implementation<C_> * get() const;
+
///\}
/**
diff --git a/paludis/util/tr1_functional.hh b/paludis/util/tr1_functional.hh
index 6679c10..51eefc8 100644
--- a/paludis/util/tr1_functional.hh
+++ b/paludis/util/tr1_functional.hh
@@ -32,6 +32,7 @@ namespace paludis
using std::tr1::mem_fn;
using std::tr1::ref;
using std::tr1::cref;
+ using std::tr1::function;
namespace placeholders
{
@@ -53,6 +54,7 @@ namespace paludis
#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include <boost/ref.hpp>
+#include <boost/function.hpp>
namespace paludis
{
@@ -62,6 +64,7 @@ namespace paludis
using boost::mem_fn;
using boost::ref;
using boost::cref;
+ using boost::function;
namespace placeholders
{
diff --git a/paludis/util/virtual_constructor-impl.hh b/paludis/util/virtual_constructor-impl.hh
index 8612383..96a1643 100644
--- a/paludis/util/virtual_constructor-impl.hh
+++ b/paludis/util/virtual_constructor-impl.hh
@@ -23,6 +23,7 @@
#include <paludis/util/virtual_constructor.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/iterator.hh>
+#include <paludis/util/tr1_functional.hh>
#include <algorithm>
#include <vector>
@@ -147,8 +148,8 @@ namespace paludis
void
VirtualConstructor<KeyType_, ValueType_, NotFoundBehaviour_>::copy_keys(T_ out_iter) const
{
- std::copy(_entries_holder->entries.begin(), _entries_holder->entries.end(), TransformInsertIterator<
- T_, SelectFirst<KeyType_, ValueType_> >(out_iter));
+ std::copy(_entries_holder->entries.begin(), _entries_holder->entries.end(), transform_inserter(out_iter,
+ paludis::tr1::mem_fn(&std::pair<KeyType_, ValueType_>::first)));
}
}
diff --git a/src/output/use_flag_pretty_printer.cc b/src/output/use_flag_pretty_printer.cc
index 8b8f873..d871244 100644
--- a/src/output/use_flag_pretty_printer.cc
+++ b/src/output/use_flag_pretty_printer.cc
@@ -23,6 +23,7 @@
#include <paludis/package_database.hh>
#include <paludis/util/collection_concrete.hh>
#include <paludis/util/iterator.hh>
+#include <paludis/util/tr1_functional.hh>
#include "colour.hh"
#include <iostream>
#include <set>
@@ -66,8 +67,7 @@ UseFlagPrettyPrinter::print_package_flags(const PackageDatabaseEntry & pkg,
return;
std::copy(metadata->ebuild_interface->iuse()->begin(), metadata->ebuild_interface->iuse()->end(),
- transform_inserter(std::inserter(iuse, iuse.begin()),
- SelectMember<IUseFlag, UseFlagName, &IUseFlag::flag>()));
+ transform_inserter(std::inserter(iuse, iuse.begin()), tr1::mem_fn(&IUseFlag::flag)));
if (old_pkg)
{
@@ -75,8 +75,7 @@ UseFlagPrettyPrinter::print_package_flags(const PackageDatabaseEntry & pkg,
fetch_repository(old_pkg->repository)->version_metadata(old_pkg->name, old_pkg->version));
if (old_metadata->ebuild_interface)
std::copy(old_metadata->ebuild_interface->iuse()->begin(), old_metadata->ebuild_interface->iuse()->end(),
- transform_inserter(std::inserter(old_iuse, old_iuse.begin()),
- SelectMember<IUseFlag, UseFlagName, &IUseFlag::flag>()));
+ transform_inserter(std::inserter(old_iuse, old_iuse.begin()), tr1::mem_fn(&IUseFlag::flag)));
}
const RepositoryUseInterface * const use_interface(environment()->package_database()->