aboutsummaryrefslogtreecommitdiff
path: root/0.18.0/paludis/repositories
diff options
context:
space:
mode:
Diffstat (limited to '0.18.0/paludis/repositories')
-rw-r--r--0.18.0/paludis/repositories/Makefile.am57
-rw-r--r--0.18.0/paludis/repositories/cran/Makefile.am117
-rw-r--r--0.18.0/paludis/repositories/cran/cran_dep_parser.cc61
-rw-r--r--0.18.0/paludis/repositories/cran/cran_dep_parser.hh24
-rw-r--r--0.18.0/paludis/repositories/cran/cran_dep_parser_TEST.cc65
-rw-r--r--0.18.0/paludis/repositories/cran/cran_description.cc109
-rw-r--r--0.18.0/paludis/repositories/cran/cran_description.hh144
-rw-r--r--0.18.0/paludis/repositories/cran/cran_installed_repository.cc725
-rw-r--r--0.18.0/paludis/repositories/cran/cran_installed_repository.hh144
-rw-r--r--0.18.0/paludis/repositories/cran/cran_installed_repository.sr23
-rw-r--r--0.18.0/paludis/repositories/cran/cran_repository.cc618
-rw-r--r--0.18.0/paludis/repositories/cran/cran_repository.hh132
-rw-r--r--0.18.0/paludis/repositories/cran/cran_repository.sr27
-rw-r--r--0.18.0/paludis/repositories/cran/cran_repository_TEST.cc97
-rwxr-xr-x0.18.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh8
-rwxr-xr-x0.18.0/paludis/repositories/cran/cran_repository_TEST_setup.sh57
-rw-r--r--0.18.0/paludis/repositories/cran/cran_version_metadata.cc47
-rw-r--r--0.18.0/paludis/repositories/cran/cran_version_metadata.hh41
-rw-r--r--0.18.0/paludis/repositories/cran/registration.cc42
-rw-r--r--0.18.0/paludis/repositories/fake/Makefile.am45
-rw-r--r--0.18.0/paludis/repositories/fake/fake_installed_repository.cc106
-rw-r--r--0.18.0/paludis/repositories/fake/fake_installed_repository.hh51
-rw-r--r--0.18.0/paludis/repositories/fake/fake_repository.cc99
-rw-r--r--0.18.0/paludis/repositories/fake/fake_repository.hh56
-rw-r--r--0.18.0/paludis/repositories/fake/fake_repository_base.cc346
-rw-r--r--0.18.0/paludis/repositories/fake/fake_repository_base.hh186
-rw-r--r--0.18.0/paludis/repositories/gems/Makefile.am148
-rw-r--r--0.18.0/paludis/repositories/gems/cache.cc338
-rw-r--r--0.18.0/paludis/repositories/gems/cache.hh52
-rw-r--r--0.18.0/paludis/repositories/gems/cache.sr18
-rw-r--r--0.18.0/paludis/repositories/gems/cache_TEST.cc93
-rwxr-xr-x0.18.0/paludis/repositories/gems/cache_TEST_cleanup.sh9
-rwxr-xr-x0.18.0/paludis/repositories/gems/cache_TEST_setup.sh33
-rw-r--r--0.18.0/paludis/repositories/gems/gems_repository.cc290
-rw-r--r--0.18.0/paludis/repositories/gems/gems_repository.hh65
-rw-r--r--0.18.0/paludis/repositories/gems/gems_repository.sr20
-rw-r--r--0.18.0/paludis/repositories/gems/gems_repository_TEST.cc51
-rwxr-xr-x0.18.0/paludis/repositories/gems/gems_repository_TEST_cleanup.sh9
-rwxr-xr-x0.18.0/paludis/repositories/gems/gems_repository_TEST_setup.sh5
-rw-r--r--0.18.0/paludis/repositories/gems/gems_repository_exceptions.cc35
-rw-r--r--0.18.0/paludis/repositories/gems/gems_repository_exceptions.hh46
-rw-r--r--0.18.0/paludis/repositories/gems/gems_version_metadata.cc43
-rw-r--r--0.18.0/paludis/repositories/gems/gems_version_metadata.hh44
-rw-r--r--0.18.0/paludis/repositories/gems/make_gems_repository.cc64
-rw-r--r--0.18.0/paludis/repositories/gems/make_gems_repository.hh32
-rw-r--r--0.18.0/paludis/repositories/gems/registration.cc40
-rw-r--r--0.18.0/paludis/repositories/gems/yaml.cc368
-rw-r--r--0.18.0/paludis/repositories/gems/yaml.hh130
-rw-r--r--0.18.0/paludis/repositories/gems/yaml_TEST.cc145
-rw-r--r--0.18.0/paludis/repositories/nothing/Makefile.am61
-rw-r--r--0.18.0/paludis/repositories/nothing/nothing_repository.cc258
-rw-r--r--0.18.0/paludis/repositories/nothing/nothing_repository.hh112
-rw-r--r--0.18.0/paludis/repositories/nothing/nothing_repository.sr25
-rw-r--r--0.18.0/paludis/repositories/nothing/registration.cc40
-rw-r--r--0.18.0/paludis/repositories/portage/Makefile.am239
-rw-r--r--0.18.0/paludis/repositories/portage/ebuild_entries.cc526
-rw-r--r--0.18.0/paludis/repositories/portage/ebuild_entries.hh70
-rw-r--r--0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.cc147
-rw-r--r--0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.hh67
-rw-r--r--0.18.0/paludis/repositories/portage/eclass_mtimes.cc68
-rw-r--r--0.18.0/paludis/repositories/portage/eclass_mtimes.hh55
-rw-r--r--0.18.0/paludis/repositories/portage/glsa.cc251
-rw-r--r--0.18.0/paludis/repositories/portage/glsa.hh113
-rw-r--r--0.18.0/paludis/repositories/portage/glsa.sr8
-rw-r--r--0.18.0/paludis/repositories/portage/make_ebuild_repository.cc165
-rw-r--r--0.18.0/paludis/repositories/portage/make_ebuild_repository.hh44
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository.cc1160
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository.hh187
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository.sr10
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_TEST.cc665
-rwxr-xr-x0.18.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh10
-rwxr-xr-x0.18.0/paludis/repositories/portage/portage_repository_TEST_setup.sh226
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_entries.cc43
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_entries.hh133
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_entry.cc32
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_exceptions.cc29
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_exceptions.hh53
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_news.cc282
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_news.hh135
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_params.cc8
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_params.hh42
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_params.sr36
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_profile.cc715
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_profile.hh127
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_profile_file.cc85
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_profile_file.hh52
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_sets.cc370
-rw-r--r--0.18.0/paludis/repositories/portage/portage_repository_sets.hh80
-rw-r--r--0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.cc45
-rw-r--r--0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.hh38
-rw-r--r--0.18.0/paludis/repositories/portage/registration.cc62
-rw-r--r--0.18.0/paludis/repositories/portage/use_desc.cc95
-rw-r--r--0.18.0/paludis/repositories/portage/use_desc.hh59
-rw-r--r--0.18.0/paludis/repositories/portage/xml_things.cc219
-rw-r--r--0.18.0/paludis/repositories/portage/xml_things.hh30
-rw-r--r--0.18.0/paludis/repositories/portage/xml_things_TEST.cc92
-rwxr-xr-x0.18.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh11
-rwxr-xr-x0.18.0/paludis/repositories/portage/xml_things_TEST_setup.sh115
-rw-r--r--0.18.0/paludis/repositories/repository_maker.cc151
-rw-r--r--0.18.0/paludis/repositories/repository_maker.hh92
-rw-r--r--0.18.0/paludis/repositories/vdb/Makefile.am90
-rw-r--r--0.18.0/paludis/repositories/vdb/registration.cc40
-rw-r--r--0.18.0/paludis/repositories/vdb/vdb_repository.cc1530
-rw-r--r--0.18.0/paludis/repositories/vdb/vdb_repository.hh203
-rw-r--r--0.18.0/paludis/repositories/vdb/vdb_repository.sr26
-rw-r--r--0.18.0/paludis/repositories/vdb/vdb_repository_TEST.cc249
-rwxr-xr-x0.18.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh11
-rwxr-xr-x0.18.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh35
-rw-r--r--0.18.0/paludis/repositories/vdb/vdb_version_metadata.cc65
-rw-r--r--0.18.0/paludis/repositories/vdb/vdb_version_metadata.hh50
-rw-r--r--0.18.0/paludis/repositories/virtuals/Makefile.am79
-rw-r--r--0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.cc297
-rw-r--r--0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.hh99
-rw-r--r--0.18.0/paludis/repositories/virtuals/registration.cc42
-rw-r--r--0.18.0/paludis/repositories/virtuals/virtuals_repository.cc383
-rw-r--r--0.18.0/paludis/repositories/virtuals/virtuals_repository.hh100
-rw-r--r--0.18.0/paludis/repositories/virtuals/vr_entry.cc26
-rw-r--r--0.18.0/paludis/repositories/virtuals/vr_entry.hh164
-rw-r--r--0.18.0/paludis/repositories/virtuals/vr_entry.sr16
119 files changed, 16748 insertions, 0 deletions
diff --git a/0.18.0/paludis/repositories/Makefile.am b/0.18.0/paludis/repositories/Makefile.am
new file mode 100644
index 000000000..d4cf1f6e8
--- /dev/null
+++ b/0.18.0/paludis/repositories/Makefile.am
@@ -0,0 +1,57 @@
+if MONOLITHIC
+
+SUBDIRS = $(BUILD_REPOSITORIES) .
+
+else
+
+SUBDIRS = . $(BUILD_REPOSITORIES)
+
+endif
+
+DIST_SUBDIRS = $(ALL_REPOSITORIES)
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+MAINTAINERCLEANFILES = Makefile.in
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+lib_LTLIBRARIES = libpaludisrepositories.la
+
+paludis_repositories_includedir = $(includedir)/paludis/repositories/
+
+paludis_repositories_include_HEADERS = \
+ repository_maker.hh
+
+libpaludisrepositories_la_SOURCES = \
+ repository_maker.cc \
+ $(paludis_repositories_include_HEADERS)
+
+libpaludisrepositories_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+if MONOLITHIC
+
+libpaludisrepositories_la_LIBADD = \
+ $(top_builddir)/paludis/repositories/virtuals/libpaludisvirtualsrepository.la \
+ $(top_builddir)/paludis/repositories/portage/libpaludisportagerepository.la \
+ $(top_builddir)/paludis/repositories/vdb/libpaludisvdbrepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ @DYNAMIC_LD_LIBS@
+
+else
+
+libpaludisrepositories_la_LIBADD = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ @DYNAMIC_LD_LIBS@
+
+endif
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
diff --git a/0.18.0/paludis/repositories/cran/Makefile.am b/0.18.0/paludis/repositories/cran/Makefile.am
new file mode 100644
index 000000000..309513ac7
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/Makefile.am
@@ -0,0 +1,117 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = cran_repository-sr.hh cran_repository-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludiscranrepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludiscranrepository.la
+
+endif
+
+paludis_repositories_cran_includedir = $(includedir)/paludis/repositories/cran/
+libpaludiscranrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_cran_include_HEADERS = \
+ cran_version_metadata.hh \
+ cran_description.hh \
+ cran_dep_parser.hh \
+ cran_repository.hh \
+ cran_repository-sr.hh \
+ cran_installed_repository.hh \
+ cran_installed_repository-sr.hh
+
+libpaludiscranrepository_la_SOURCES = \
+ cran_version_metadata.cc \
+ cran_description.cc \
+ cran_dep_parser.cc \
+ cran_repository.cc \
+ cran_installed_repository.cc \
+ registration.cc \
+ $(paludis_repositories_cran_include_HEADERS)
+
+if ! MONOLITHIC
+
+libpaludiscranrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+TESTS = cran_dep_parser_TEST cran_repository_TEST
+
+cran_dep_parser_TEST_SOURCES = cran_dep_parser_TEST.cc
+
+cran_dep_parser_TEST_LDADD= \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiscranrepository.la
+
+cran_repository_TEST_SOURCES = cran_repository_TEST.cc
+
+cran_repository_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiscranrepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/environment/test/libpaludistestenvironment.la \
+ $(DYNAMIC_LD_LIBS)
+
+cran_repository_TEST_CXXFLAGS = -I$(top_srcdir)
+
+EXTRA_DIST = \
+ cran_repository_TEST.cc \
+ cran_repository_TEST_setup.sh \
+ cran_repository_TEST_cleanup.sh \
+ cran_repository.sr \
+ cran_repository-sr.hh \
+ cran_repository-sr.cc \
+ cran_installed_repository.sr \
+ cran_installed_repository-sr.hh \
+ cran_installed_repository-sr.cc
+
+BUILT_SOURCES = \
+ cran_repository-sr.hh \
+ cran_repository-sr.cc \
+ cran_installed_repository-sr.hh \
+ cran_installed_repository-sr.cc
+
+check_PROGRAMS = $(TESTS)
+check_SCRIPTS = cran_repository_TEST_setup.sh cran_repository_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ CRAN_BASH_DIR="$(top_srcdir)/cran/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ bash $(top_srcdir)/test/run_test.sh
+
+cran_repository-sr.hh : cran_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/cran_repository.sr > $@
+
+cran_repository-sr.cc : cran_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/cran_repository.sr > $@
+
+cran_installed_repository-sr.hh : cran_installed_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/cran_installed_repository.sr > $@
+
+cran_installed_repository-sr.cc : cran_installed_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/cran_installed_repository.sr > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in $(SUBDIRS) ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/0.18.0/paludis/repositories/cran/cran_dep_parser.cc b/0.18.0/paludis/repositories/cran/cran_dep_parser.cc
new file mode 100644
index 000000000..3de5f370f
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_dep_parser.cc
@@ -0,0 +1,61 @@
+#include <paludis/dep_atom.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_description.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <string>
+#include <list>
+
+using namespace paludis;
+
+std::tr1::shared_ptr<const CompositeDepAtom>
+CRANDepParser::parse(const std::string & s)
+{
+ Context context("When parsing CRAN 'Depends:' string: '" + s + "':");
+
+ std::tr1::shared_ptr<CompositeDepAtom> result(new AllDepAtom);
+ Tokeniser<delim_kind::AnyOfTag, delim_mode::DelimiterTag> atom_tokeniser(",");
+
+ std::list<std::string> atoms;
+ atom_tokeniser.tokenise(s, std::back_inserter(atoms));
+ std::list<std::string>::const_iterator a(atoms.begin()), a_end(atoms.end());
+ for ( ; a != a_end ; ++a)
+ {
+ Context local_context("When processing token '" + *a + "':");
+
+ std::string aa = strip_leading(strip_trailing(*a, ")"), " \t");
+
+ std::string name, tmp, version, range;
+ std::string::size_type p(aa.find('('));
+ if ((std::string::npos != p))
+ {
+ name = strip_leading(strip_trailing(aa.substr(0, p), " \t"), " \t");
+ tmp = aa.substr(p + 1);
+ p = tmp.find(')');
+ aa = tmp.substr(0, p);
+ version = strip_trailing(strip_leading(aa, " \t(<>=~"), " )\t\n");
+ range = strip_trailing(strip_leading(aa.substr(0, aa.find(version)), " \t"), " \t\n");
+ }
+ else
+ name = strip_leading(strip_trailing(aa, " \t"), " \t");
+
+ CRANDescription::normalise_name(name);
+ CRANDescription::normalise_version(version);
+
+ if ("R" == name)
+ name = "dev-lang/R";
+ else
+ name = "cran/" + name;
+
+ std::string atom_string;
+ if (version.empty() || range.empty())
+ atom_string = name;
+ else
+ atom_string = range + name + "-" + version;
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(atom_string));
+ result->add_child(atom);
+ }
+
+ return result;
+}
diff --git a/0.18.0/paludis/repositories/cran/cran_dep_parser.hh b/0.18.0/paludis/repositories/cran/cran_dep_parser.hh
new file mode 100644
index 000000000..c862db2c0
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_dep_parser.hh
@@ -0,0 +1,24 @@
+#ifndef PALUDIS_GUARD_PALUDIS_CRAN_DEP_PARSER_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_DEP_PARSER_HH 1
+
+#include <paludis/dep_atom.hh>
+#include <string>
+
+namespace paludis
+{
+ /**
+ * The CRANDepParser conversts a string representation of a CRAN Depends:
+ * specification into a DepAtom instance.
+ *
+ * \ingroup grpdepparser
+ */
+ struct PALUDIS_VISIBLE CRANDepParser
+ {
+ /**
+ * Parse function.
+ */
+ static std::tr1::shared_ptr<const CompositeDepAtom> parse(const std::string & s);
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/cran/cran_dep_parser_TEST.cc b/0.18.0/paludis/repositories/cran/cran_dep_parser_TEST.cc
new file mode 100644
index 000000000..4bea61bbe
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_dep_parser_TEST.cc
@@ -0,0 +1,65 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/dep_atom.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/dep_atom_pretty_printer.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/environment/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+/** \file
+ * Test cases for CRANRepository.
+ *
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test CRANDepParser::parse to parse well formed CRAN Depends: strings.
+ *
+ */
+ struct CRANDepParserTest : TestCase
+ {
+ CRANDepParserTest() : TestCase("DepParser") { }
+
+ void run()
+ {
+ DepAtomPrettyPrinter d1(0, false), d2(0, false), d3(0, false);
+ // test R dependency
+ std::string dep1("R (>= 2.0.0)");
+ CRANDepParser::parse(dep1)->accept(&d1);
+ TEST_CHECK_EQUAL(stringify(d1), "( >=dev-lang/R-2.0.0 ) ");
+ // test varying whitespaces
+ std::string dep2("testpackage1 \t(<1.9)");
+ CRANDepParser::parse(dep2)->accept(&d2);
+ TEST_CHECK_EQUAL(stringify(d2), "( <cran/testpackage1-1.9 ) ");
+ // test for package-name and version normalisation
+ std::string dep3("R.matlab (>= 2.3-1)");
+ CRANDepParser::parse(dep3)->accept(&d3);
+ TEST_CHECK_EQUAL(stringify(d3), "( >=cran/R-matlab-2.3.1 ) ");
+ }
+ } test_cran_dep_parser;
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_description.cc b/0.18.0/paludis/repositories/cran/cran_description.cc
new file mode 100644
index 000000000..a6f1dea07
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_description.cc
@@ -0,0 +1,109 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Danny van Dyk <kugelfang@gentoo.org>
+ * 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/cran/cran_description.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_version_metadata.hh>
+#include <paludis/config_file.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <string>
+
+using namespace paludis;
+
+CRANDescription::CRANDescription(const std::string & n, const FSEntry & f, bool installed) :
+ name("cran/" + n),
+ version("0"),
+ metadata(new CRANVersionMetadata(installed))
+{
+ Context context("When parsing file '" + stringify(f) + "' for package '" + n + "':");
+
+ if (! f.is_regular_file())
+ {
+ metadata->eapi = "UNKNOWN";
+ Log::get_instance()->message(ll_warning, lc_context, "Unexpected irregular file: '" + stringify(f) + "'.");
+ return;
+ }
+
+ LineConfigFile file(f);
+ LineConfigFile::Iterator l(file.begin()), l_end(file.end());
+
+ // Fill in default values
+ metadata->slot = SlotName("0");
+ metadata->cran_interface->keywords = std::string("*");
+ metadata->eapi = "CRAN-1";
+
+ std::string key;
+ for ( ; l != l_end ; ++l)
+ {
+ Context local_context("When parsing line '" + *l + "':");
+
+ std::string line(strip_leading(strip_trailing(*l, " \t\r\n"), " \t\r\n")), value;
+ std::string::size_type pos(line.find(':'));
+ if (std::string::npos == pos)
+ {
+ value = strip_leading(strip_trailing(line, " \t"), " \t");
+ }
+ else
+ {
+ key = strip_leading(strip_trailing(line.substr(0, pos), " \t"), " \t");
+ value = strip_leading(strip_trailing(line.substr(pos + 1), " \t\r\n"), " \t\r\n");
+ }
+
+ if (("Package" == key) || ("Bundle" == key))
+ {
+ metadata->cran_interface->package = value;
+ metadata->homepage = "http://cran.r-project.org/src/contrib/Descriptions/" + value + ".html";
+ if ("Package" == key)
+ {
+ CRANDescription::normalise_name(value);
+ if (n != value)
+ Log::get_instance()->message(ll_warning, lc_context, "Inconsistent package name in file '" +
+ stringify(name) + "': '" + n + "', '" + value + "':");
+ }
+ else
+ {
+ metadata->cran_interface->is_bundle = true;
+ }
+ }
+ else if ("Version" == key)
+ {
+ metadata->cran_interface->version = value;
+ normalise_version(value);
+ version = VersionSpec(value);
+ }
+ else if ("Title" == key)
+ {
+ metadata->description = value;
+ }
+ else if ("Depends" == key)
+ {
+ if (value.empty())
+ value = "R";
+ else
+ value.append(", R");
+ metadata->deps_interface->build_depend_string = value;
+ metadata->deps_interface->run_depend_string = value;
+ }
+ else if ("Suggests" == key)
+ metadata->deps_interface->suggested_depend_string = value;
+ }
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_description.hh b/0.18.0/paludis/repositories/cran/cran_description.hh
new file mode 100644
index 000000000..b1522b78f
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_description.hh
@@ -0,0 +1,144 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ * 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_CRAN_DESCRIPTION_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_DESCRIPTION_HH 1
+
+#include <paludis/version_metadata.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+
+namespace paludis
+{
+ /**
+ * CRANDescription as used by CRANRepository and CRANInstalledRepository
+ */
+ struct PALUDIS_VISIBLE CRANDescription
+ {
+ /// Our package name.
+ QualifiedPackageName name;
+
+ /// Our package version.
+ VersionSpec version;
+
+ /// Our metadata, may be zero.
+ std::tr1::shared_ptr<VersionMetadata> metadata;
+
+ /// Our installed date.
+ time_t installed_time;
+
+ /// Turn a CRAN package name into a paludis package name.
+ static void normalise_name(std::string & s)
+ {
+ std::replace_if(s.begin(), s.end(), std::bind2nd(std::equal_to<char>(), '.'), '-');
+ }
+
+ /// Turn a paludis package name into a CRAN package name.
+ static void denormalise_name(std::string & s)
+ {
+ std::replace_if(s.begin(), s.end(), std::bind2nd(std::equal_to<char>(), '-'), '.');
+ }
+
+ /// Turn a CRAN package version into a paludis package version.
+ static void normalise_version(std::string & s)
+ {
+ std::replace_if(s.begin(), s.end(), std::bind2nd(std::equal_to<char>(), '-'), '.');
+ }
+
+ /// Constructor
+ CRANDescription(const std::string & n, const FSEntry & f, bool installed);
+
+ /// Comparison operator
+ bool operator< (const CRANDescription & other) const
+ {
+ if (name < other.name)
+ return true;
+ if (name > other.name)
+ return false;
+ if (version < other.version)
+ return true;
+ return false;
+ }
+
+ /**
+ * Compare a CRANDescription by name only.
+ *
+ * \ingroup grpcrandesc
+ */
+ struct PALUDIS_VISIBLE ComparePackage
+ {
+ ///\name Comparison operators
+ ///\{
+
+ bool operator() (const QualifiedPackageName & c, const CRANDescription & d) const
+ {
+ return c < d.name;
+ }
+
+ bool operator() (const CRANDescription & d, const QualifiedPackageName & c) const
+ {
+ return d.name < c;
+ }
+
+ ///\}
+ };
+
+ /**
+ * Compare a CRANIDescription by name and version.
+ *
+ * \ingroup grpcrandesc
+ */
+ struct PALUDIS_VISIBLE CompareVersion
+ {
+ ///\name Comparison operators
+ ///\{
+
+ bool operator() (const std::pair<QualifiedPackageName, VersionSpec> & c,
+ const CRANDescription & d) const
+ {
+ if (c.first < d.name)
+ return true;
+ else if (c.first > d.name)
+ return false;
+ else if (c.second < d.version)
+ return true;
+ else
+ return false;
+ }
+
+ bool operator() (const CRANDescription & d,
+ const std::pair<QualifiedPackageName, VersionSpec> & c) const
+ {
+ if (d.name < c.first)
+ return true;
+ else if (d.name > c.first)
+ return false;
+ else if (d.version < c.second)
+ return true;
+ else
+ return false;
+ }
+
+ ///\}
+ };
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/cran/cran_installed_repository.cc b/0.18.0/paludis/repositories/cran/cran_installed_repository.cc
new file mode 100644
index 000000000..1317587ce
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_installed_repository.cc
@@ -0,0 +1,725 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006,2007 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/hashed_containers.hh>
+#include <paludis/config_file.hh>
+#include <paludis/match_package.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repositories/cran/cran_description.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_installed_repository.hh>
+#include <paludis/repositories/cran/cran_version_metadata.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <fstream>
+#include <functional>
+#include <algorithm>
+#include <vector>
+
+using namespace paludis;
+
+#include <paludis/repositories/cran/cran_installed_repository-sr.cc>
+
+namespace paludis
+{
+ /// Map for metadata.
+ typedef MakeHashedMap<std::pair<QualifiedPackageName, VersionSpec>, std::tr1::shared_ptr<VersionMetadata> >::Type MetadataMap;
+
+ template <>
+ struct Implementation<CRANInstalledRepository>
+ {
+ CRANInstalledRepositoryParams params;
+
+ /// Our owning env.
+ const Environment * const env;
+
+ /// Our base location.
+ FSEntry location;
+
+ /// Root location
+ FSEntry root;
+
+ /// World file.
+ FSEntry world_file;
+
+ // Do we have entries loaded?
+ mutable bool entries_valid;
+
+ mutable std::vector<CRANDescription> entries;
+
+ /// Load entries.
+ void load_entries() const;
+
+ /// Metadata cache
+ mutable MetadataMap metadata;
+
+ /// Provide map.
+ mutable std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Constructor.
+ Implementation(const CRANInstalledRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+ };
+}
+
+Implementation<CRANInstalledRepository>::Implementation(const CRANInstalledRepositoryParams & p) :
+ params(p),
+ env(p.environment),
+ location(p.location),
+ root(p.root),
+ world_file(p.world),
+ entries_valid(false)
+{
+}
+
+Implementation<CRANInstalledRepository>::~Implementation()
+{
+}
+
+void
+Implementation<CRANInstalledRepository>::load_entries() const
+{
+ Context context("When loading CRANInstalledRepository entries from '" +
+ stringify(location) + "':");
+
+ entries.clear();
+ entries_valid = true;
+ try
+ {
+ for (DirIterator d(location), d_end ; d != d_end ; ++d)
+ {
+ Context local_context("When parsing directoryy '" + stringify(*d) + "'.");
+ if (! d->is_directory())
+ continue;
+
+ FSEntry f(FSEntry(stringify(*d)) / "DESCRIPTION");
+ if (! f.is_regular_file())
+ continue;
+
+ std::string n(d->basename());
+ CRANDescription::normalise_name(n);
+
+ CRANDescription desc(n, f, true);
+ entries.push_back(desc);
+
+ QualifiedPackageName q("cran/" + n);
+ metadata.insert(std::make_pair(std::make_pair(q, VersionSpec(desc.version)), desc.metadata));
+ }
+
+ if (! FSEntry(location / "paludis" / "bundles").is_directory())
+ return;
+
+ // Load Bundle Metadata
+ for (DirIterator f(location / "paludis" / "bundles"), f_end ; f != f_end ; ++f)
+ {
+ Context local_context("When parsing file '" + stringify(*f) + "'.");
+
+ if (! f->is_regular_file())
+ {
+ continue;
+ }
+
+ std::string n(f->basename());
+ std::string::size_type pos(n.find_last_of("."));
+ if (std::string::npos != pos)
+ n.erase(pos);
+ CRANDescription::normalise_name(n);
+
+ CRANDescription desc(n, *f, true);
+ entries.push_back(desc);
+
+ QualifiedPackageName q("cran/" + n);
+ metadata.insert(std::make_pair(std::make_pair(q, VersionSpec(desc.version)), desc.metadata));
+ }
+
+ }
+ catch (...)
+ {
+ entries_valid = false;
+ throw;
+ }
+}
+
+CRANInstalledRepository::CRANInstalledRepository(const CRANInstalledRepositoryParams & p) :
+ Repository(RepositoryName("cran_installed"),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(0)
+ .installed_interface(this)
+ .contents_interface(this)
+ .news_interface(0)
+ .sets_interface(this)
+ .syncable_interface(0)
+ .uninstallable_interface(this)
+ .use_interface(0)
+ .world_interface(this)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .virtuals_interface(0)
+ .provides_interface(0)
+ .config_interface(0)
+ .destination_interface(this),
+ "cran_installed"),
+ PrivateImplementationPattern<CRANInstalledRepository>(new Implementation<CRANInstalledRepository>(p))
+{
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->location));
+ config_info->add_kv("root", stringify(_imp->root));
+ config_info->add_kv("format", std::string("cran-installed"));
+
+ _info->add_section(config_info);
+}
+
+CRANInstalledRepository::~CRANInstalledRepository()
+{
+}
+
+bool
+CRANInstalledRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ return (CategoryNamePart("cran") == c);
+}
+
+bool
+CRANInstalledRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) +
+ "' in " + stringify(name()) + ":");
+
+ if (! do_has_category_named(q.category))
+ return false;
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::pair<std::vector<CRANDescription>::const_iterator, std::vector<CRANDescription>::const_iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), q,
+ CRANDescription::ComparePackage()));
+
+ return r.first != r.second;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+CRANInstalledRepository::do_category_names() const
+{
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ result->insert(CategoryNamePart("cran"));
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+CRANInstalledRepository::do_package_names(const CategoryNamePart & c) const
+{
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ if (! do_has_category_named(c))
+ return result;
+
+ std::vector<CRANDescription>::const_iterator e(_imp->entries.begin()), e_end(_imp->entries.end());
+ for ( ; e != e_end ; ++e)
+ result->insert(e->name);
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+CRANInstalledRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ std::tr1::shared_ptr<VersionSpecCollection> result(new VersionSpecCollection::Concrete);
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ for (std::vector<CRANDescription>::const_iterator e(_imp->entries.begin()), e_end(_imp->entries.end()) ;
+ e != e_end ; ++e)
+ if (n == e->name)
+ result->insert(e->version);
+
+ return result;
+}
+
+bool
+CRANInstalledRepository::do_has_version(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When checking for version '" + stringify(v) + "' in '"
+ + stringify(q) + "' in " + stringify(name()) + ":");
+
+ std::tr1::shared_ptr<const VersionSpecCollection> versions(do_version_specs(q));
+ return versions->end() != versions->find(v);
+}
+
+namespace
+{
+ /**
+ * Fetch the contents of a VDB file.
+ *
+ * \ingroup grpcranrepository
+ */
+ std::string
+ file_contents(const FSEntry & location, const QualifiedPackageName & name,
+ const std::string & key)
+ {
+ Context context("When loading metadata for '" + stringify(name)
+ + "' key '" + key + "' from '" + stringify(location) + "':");
+
+ FSEntry f(location / stringify(name.package));
+ if (! (f / key).is_regular_file())
+ return "";
+
+ std::ifstream ff(stringify(f / key).c_str());
+ if (! ff)
+ throw InternalError("CRANInstalledRepository", "Could not read '" + stringify(f / key) + "'");
+ return strip_leading(strip_trailing(std::string((std::istreambuf_iterator<char>(ff)),
+ std::istreambuf_iterator<char>()), " \t\n"), " \t\n");
+ }
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+CRANInstalledRepository::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (_imp->metadata.end() != _imp->metadata.find(
+ std::make_pair(q, v)))
+ return _imp->metadata.find(std::make_pair(q, v))->second;
+
+ Context context("When fetching metadata for " + stringify(q) +
+ "-" + stringify(v));
+
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ std::tr1::shared_ptr<VersionMetadata> result;
+
+ FSEntry d(_imp->location);
+ d /= stringify(q.package);
+ d /= "DESCRIPTION";
+
+ if (d.is_regular_file())
+ {
+ CRANDescription description(stringify(q.package), d, true);
+ // Don't put this into CRANDescription, as it's only relevant to CRANInstalledRepository
+ std::string repo(file_contents(_imp->location, q, "REPOSITORY"));
+ if (! repo.empty())
+ description.metadata->origins_interface->source.reset(new PackageDatabaseEntry(stringify(q.package), v,
+ RepositoryName(repo)));
+ result = description.metadata;
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "has_version failed for request for '" +
+ stringify(q) + "-" + stringify(v) + "' in repository '" +
+ stringify(name()) + "': No DESCRIPTION file present.");
+ result.reset(new CRANVersionMetadata(true));
+ result->eapi = "UNKNOWN";
+ return result;
+ }
+
+ _imp->metadata.insert(std::make_pair(std::make_pair(q, v), result));
+ return result;
+}
+
+std::tr1::shared_ptr<const Contents>
+CRANInstalledRepository::do_contents(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ Context context("When fetching contents for " + stringify(q) +
+ "-" + stringify(v));
+
+ std::tr1::shared_ptr<Contents> result(new Contents);
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ if (! has_version(q, v))
+ return result;
+
+ std::string pn = stringify(q.package);
+ CRANDescription::normalise_name(pn);
+ FSEntry f(_imp->location / "paludis" / pn / "CONTENTS");
+ if (! f.is_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS lookup failed for request for' " +
+ stringify(q) + "-" + stringify(v) + "' in CRANInstalled '" +
+ stringify(_imp->location) + "'");
+ return result;
+ }
+
+ std::ifstream ff(stringify(f).c_str());
+ if (! ff)
+ throw InternalError(PALUDIS_HERE, "TODO reading " + stringify(_imp->location) + " name " +
+ stringify(q) + " version " + stringify(v) + " CONTENTS"); /// \todo
+
+ std::string line;
+ unsigned line_number(0);
+ while (std::getline(ff, line))
+ {
+ ++line_number;
+
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(line, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if (tokens.size() < 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ if ("obj" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsMiscEntry(tokens.at(1))));
+ else if ("sym" == tokens.at(0))
+ {
+ if (tokens.size() < 4)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken sym line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsSymEntry(
+ tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return result;
+}
+
+time_t
+CRANInstalledRepository::do_installed_time(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When finding installed time for '" + stringify(q) +
+ "-" + stringify(v) + "':");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::vector<CRANDescription>::iterator r(_imp->entries.begin()), r_end(_imp->entries.end());
+ for ( ; r != r_end ; ++r)
+ {
+ if (q == r->name)
+ break;
+ }
+
+ if (r == r_end)
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+ else
+ {
+ if (0 == r->installed_time)
+ {
+ std::string pn(stringify(q.package));
+ CRANDescription::normalise_name(pn);
+ FSEntry f(_imp->location / "paludis" / pn / "CONTENTS");
+ try
+ {
+ r->installed_time = f.ctime();
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Can't get ctime of '"
+ + stringify(f) + "' due to exception '" + e.message() + "' (" + e.what()
+ + ")");
+ r->installed_time = 1;
+ }
+ }
+ return r->installed_time;
+ }
+}
+
+std::tr1::shared_ptr<Repository>
+CRANInstalledRepository::make_cran_installed_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ Context context("When making CRAN installed repository from repo_file '" +
+ (m->end() == m->find("repo_file") ? std::string("?") : m->find("repo_file")->second) + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw CRANInstalledRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string root;
+ if (m->end() == m->find("root") || ((root = m->find("root")->second)).empty())
+ root = "/";
+
+ std::string world;
+ if (m->end() == m->find("world") || ((world = m->find("world")->second)).empty())
+ world = location + "/world";
+
+ return std::tr1::shared_ptr<Repository>(new CRANInstalledRepository(CRANInstalledRepositoryParams::create()
+ .environment(env)
+ .location(location)
+ .root(root)
+ .world(world)));
+}
+
+CRANInstalledRepositoryConfigurationError::CRANInstalledRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("CRAN installed repository configuration error: " + msg)
+{
+}
+
+bool
+CRANInstalledRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+CRANInstalledRepository::do_uninstall(const QualifiedPackageName & q, const VersionSpec & v,
+ const InstallOptions &) const
+{
+ Context context("When uninstalling '" + stringify(q) + "-" + stringify(v) +
+ "' from '" + stringify(name()) + "':");
+
+ if (! _imp->location.is_directory())
+ throw PackageInstallActionError("Couldn't uninstall '" + stringify(q) + "-" +
+ stringify(v) + "' because its location ('" + stringify(_imp->location) + "') is not a directory");
+
+ std::tr1::shared_ptr<const VersionMetadata> vm(do_version_metadata(q, v));
+
+ MakeEnvCommand cmd(LIBEXECDIR "/paludis/cran.bash unmerge", "");
+ cmd = cmd("PN", vm->cran_interface->package);
+ cmd = cmd("PV", stringify(v));
+ cmd = cmd("PALUDIS_CRAN_LIBRARY", stringify(_imp->location));
+ cmd = cmd("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"));
+ cmd = cmd("PALUDIS_BASHRC_FILES", _imp->env->bashrc_files());
+
+ if (0 != run_command(cmd))
+ throw PackageUninstallActionError("Couldn't unmerge '" + stringify(q) + "-" + stringify(v) + "'");
+}
+
+std::tr1::shared_ptr<DepAtom>
+CRANInstalledRepository::do_package_set(const SetName & s) const
+{
+ Context context("When fetching package set '" + stringify(s) + "' from '" +
+ stringify(name()) + "':");
+
+ if ("everything" == s.data())
+ {
+ std::tr1::shared_ptr<AllDepAtom> result(new AllDepAtom);
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ for (std::vector<CRANDescription>::const_iterator p(_imp->entries.begin()),
+ p_end(_imp->entries.end()) ; p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(p->name));
+ result->add_child(atom);
+ }
+
+ return result;
+ }
+ else if ("world" == s.data())
+ {
+ std::tr1::shared_ptr<AllDepAtom> result(new AllDepAtom);
+
+ if (_imp->world_file.exists())
+ {
+ LineConfigFile world(_imp->world_file);
+
+ for (LineConfigFile::Iterator line(world.begin()), line_end(world.end()) ;
+ line != line_end ; ++line)
+ {
+ try
+ {
+ if (std::string::npos == line->find('/'))
+ {
+ std::tr1::shared_ptr<DepAtom> atom(_imp->env->package_set(SetName(*line)));
+ if (atom)
+ result->add_child(atom);
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Entry '" + stringify(*line) + "' in world file '" + stringify(_imp->world_file)
+ + "' is not a known set");
+ }
+ else
+ {
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(QualifiedPackageName(*line)));
+ result->add_child(atom);
+ }
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Entry '" + stringify(*line) + "' in world file '" + stringify(_imp->world_file)
+ + "' gave error '" + e.message() + "' (" + e.what() + ")");
+ }
+ }
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context, "World file '" + stringify(_imp->world_file)
+ + "' doesn't exist");
+
+ return result;
+ }
+ else
+ return std::tr1::shared_ptr<DepAtom>();
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+CRANInstalledRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ std::tr1::shared_ptr<SetsCollection> result(new SetsCollection::Concrete);
+ result->insert(SetName("everything"));
+ result->insert(SetName("world"));
+ return result;
+}
+
+void
+CRANInstalledRepository::invalidate()
+{
+ _imp.reset(new Implementation<CRANInstalledRepository>(_imp->params));
+}
+
+void
+CRANInstalledRepository::add_string_to_world(const std::string & n) const
+{
+ bool found(false);
+
+ if (_imp->world_file.exists())
+ {
+ LineConfigFile world(_imp->world_file);
+
+ for (LineConfigFile::Iterator line(world.begin()), line_end(world.end()) ;
+ line != line_end ; ++line)
+ if (*line == n)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (! found)
+ {
+ std::ofstream world(stringify(_imp->world_file).c_str(), std::ios::out | std::ios::app);
+ if (! world)
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot append to world file '"
+ + stringify(_imp->world_file) + "', skipping world update");
+ else
+ world << n << std::endl;
+ }
+}
+
+void
+CRANInstalledRepository::remove_string_from_world(const std::string & n) const
+{
+ std::list<std::string> world_lines;
+
+ if (_imp->world_file.exists())
+ {
+ std::ifstream world_file(stringify(_imp->world_file).c_str());
+
+ if (! world_file)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot read world file '"
+ + stringify(_imp->world_file) + "', skipping world update");
+ return;
+ }
+
+ std::string line;
+ while (std::getline(world_file, line))
+ {
+ if (strip_leading(strip_trailing(line, " \t"), "\t") != n)
+ world_lines.push_back(line);
+ else
+ Log::get_instance()->message(ll_debug, lc_context, "Removing line '"
+ + line + "' from world file '" + stringify(_imp->world_file));
+ }
+ }
+
+ std::ofstream world_file(stringify(_imp->world_file).c_str());
+
+ if (! world_file)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot write world file '"
+ + stringify(_imp->world_file) + "', skipping world update");
+ return;
+ }
+
+ std::copy(world_lines.begin(), world_lines.end(),
+ std::ostream_iterator<std::string>(world_file, "\n"));
+}
+
+bool
+CRANInstalledRepository::is_suitable_destination_for(const PackageDatabaseEntry & e) const
+{
+ return _imp->env->package_database()->fetch_repository(e.repository)->format() == "cran";
+}
+
+void
+CRANInstalledRepository::add_to_world(const QualifiedPackageName & n) const
+{
+ add_string_to_world(stringify(n));
+}
+
+void
+CRANInstalledRepository::remove_from_world(const QualifiedPackageName & n) const
+{
+ remove_string_from_world(stringify(n));
+}
+
+void
+CRANInstalledRepository::add_to_world(const SetName & n) const
+{
+ add_string_to_world(stringify(n));
+}
+
+void
+CRANInstalledRepository::remove_from_world(const SetName & n) const
+{
+ remove_string_from_world(stringify(n));
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_installed_repository.hh b/0.18.0/paludis/repositories/cran/cran_installed_repository.hh
new file mode 100644
index 000000000..9c6f77213
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_installed_repository.hh
@@ -0,0 +1,144 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_CRAN_INSTALLED_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_INSTALLED_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry.hh>
+
+/** \file
+ * Declarations for CRANInstalledRepository.
+ *
+ * \ingroup grpcraninstrepository
+ */
+
+
+namespace paludis
+{
+
+#include <paludis/repositories/cran/cran_installed_repository-sr.hh>
+
+ /**
+ * A CRANInstalledRepository represents the database used for
+ * installed CRAN packages.
+ *
+ * \ingroup grpcraninstrepository
+ */
+ class PALUDIS_VISIBLE CRANInstalledRepository :
+ public Repository,
+ public RepositoryInstalledInterface,
+ public RepositoryContentsInterface,
+ public RepositoryUninstallableInterface,
+ public RepositorySetsInterface,
+ public RepositoryWorldInterface,
+ public RepositoryDestinationInterface,
+ public PrivateImplementationPattern<CRANInstalledRepository>
+ {
+ protected:
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const Contents> do_contents(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual time_t do_installed_time(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_uninstall(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual std::tr1::shared_ptr<DepAtom> do_package_set(const SetName &) const;
+
+ virtual std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+
+ virtual void add_string_to_world(const std::string &) const;
+ virtual void remove_string_from_world(const std::string &) const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ CRANInstalledRepository(const CRANInstalledRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static std::tr1::shared_ptr<Repository> make_cran_installed_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m);
+
+ /**
+ * Destructor.
+ */
+ ~CRANInstalledRepository();
+
+ virtual void invalidate();
+
+ virtual void add_to_world(const QualifiedPackageName &) const;
+
+ virtual void remove_from_world(const QualifiedPackageName &) const;
+
+ virtual void add_to_world(const SetName &) const;
+
+ virtual void remove_from_world(const SetName &) const;
+
+ virtual bool is_suitable_destination_for(const PackageDatabaseEntry &) const;
+ };
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * PortageRepository::make_portage_repository.
+ *
+ * \ingroup grpcraninstrepository
+ * \ingroup grpexceptions
+ */
+ class PALUDIS_VISIBLE CRANInstalledRepositoryConfigurationError : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ CRANInstalledRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/cran/cran_installed_repository.sr b/0.18.0/paludis/repositories/cran/cran_installed_repository.sr
new file mode 100644
index 000000000..1444c161e
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_installed_repository.sr
@@ -0,0 +1,23 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_CRANInstalledRepositoryParams()
+{
+ key environment "const Environment *"
+ key location FSEntry
+ key root FSEntry
+ key world FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a CRANInstalledRepository
+ *
+ * \see CRANInstalledRepository
+ * \ingroup grpcraninstrepository
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_repository.cc b/0.18.0/paludis/repositories/cran/cran_repository.cc
new file mode 100644
index 000000000..9016344f2
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_repository.cc
@@ -0,0 +1,618 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006,2007 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <paludis/dep_atom.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/config_file.hh>
+#include <paludis/match_package.hh>
+#include <paludis/package_database_entry.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_description.hh>
+#include <paludis/repositories/cran/cran_repository.hh>
+#include <paludis/repositories/cran/cran_version_metadata.hh>
+#include <paludis/repositories/repository_maker.hh>
+#include <paludis/syncer.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/random.hh>
+#include <paludis/util/save.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <map>
+#include <list>
+#include <fstream>
+#include <functional>
+#include <algorithm>
+#include <vector>
+#include <deque>
+#include <limits>
+
+#include <strings.h>
+#include <ctype.h>
+
+/** \file
+ * Implementation CRANRepository.
+ *
+ * \ingroup grpcranrepository
+ */
+
+using namespace paludis;
+
+#include <paludis/repositories/cran/cran_repository-sr.cc>
+
+namespace paludis
+{
+ /// Map for versions.
+ typedef MakeHashedMap<QualifiedPackageName, VersionSpec>::Type VersionsMap;
+
+ /// Map for packages.
+ typedef MakeHashedMap<QualifiedPackageName, bool>::Type PackagesMap;
+
+ /// Map for mirrors.
+ typedef MakeHashedMap<std::string, std::list<std::string> >::Type MirrorMap;
+
+ /// Map for metadata.
+ typedef MakeHashedMap<std::pair<QualifiedPackageName, VersionSpec>, std::tr1::shared_ptr<VersionMetadata> >::Type MetadataMap;
+
+ /**
+ * Implementation data for a CRANRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+ template <>
+ struct Implementation<CRANRepository>
+ {
+ CRANRepositoryParams params;
+
+ /// Our owning env.
+ const Environment * const env;
+
+ /// Our base location.
+ FSEntry location;
+
+ /// Distfiles dir
+ FSEntry distdir;
+
+ /// Mirror URL
+ std::string mirror;
+
+ /// Sync URL
+ std::string sync;
+
+ /// Build root location
+ FSEntry buildroot;
+
+ /// Root location
+ FSEntry root;
+
+ /// Library location
+ FSEntry library;
+
+ /// Have we loaded our category names?
+ mutable bool has_packages;
+
+ /// Our package names, and whether we have a fully loaded list of
+ /// version specs for that category.
+ mutable PackagesMap package_names;
+
+ /// Our version specs for each package.
+ mutable VersionsMap version_specs;
+
+ /// Metadata cache.
+ mutable MetadataMap metadata;
+
+ /// Do we have mirrors?
+ mutable bool has_mirrors;
+
+ /// Mirrors.
+ mutable MirrorMap mirrors;
+
+ /// Constructor.
+ Implementation(const CRANRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+ };
+}
+
+Implementation<CRANRepository>::Implementation(const CRANRepositoryParams & p) :
+ params(p),
+ env(p.environment),
+ location(p.location),
+ distdir(p.distdir),
+ mirror(p.mirror),
+ sync(p.sync),
+ buildroot(p.buildroot),
+ root(p.root),
+ library(p.library),
+ has_packages(false),
+ has_mirrors(false)
+{
+}
+
+Implementation<CRANRepository>::~Implementation()
+{
+}
+
+
+CRANRepository::CRANRepository(const CRANRepositoryParams & p) :
+ Repository(CRANRepository::fetch_repo_name(stringify(p.location)),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(this)
+ .installed_interface(0)
+ .news_interface(0)
+ .sets_interface(this)
+ .syncable_interface(this)
+ .uninstallable_interface(0)
+ .use_interface(0)
+ .world_interface(0)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .provides_interface(0)
+ .destination_interface(0)
+ .virtuals_interface(0)
+ .config_interface(0)
+ .contents_interface(0),
+ "cran"),
+ PrivateImplementationPattern<CRANRepository>(new Implementation<CRANRepository>(p))
+{
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->location));
+ config_info->add_kv("distdir", stringify(_imp->distdir));
+ config_info->add_kv("format", "cran");
+ config_info->add_kv("buildroot", stringify(_imp->buildroot));
+ config_info->add_kv("root", stringify(_imp->root));
+ config_info->add_kv("library", stringify(_imp->library));
+ config_info->add_kv("sync", _imp->sync);
+
+ _info->add_section(config_info);
+}
+
+CRANRepository::~CRANRepository()
+{
+}
+
+bool
+CRANRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ Context context("When checking for category '" + stringify(c) +
+ "' in " + stringify(name()) + ":");
+
+ return "cran" == stringify(c);
+}
+
+bool
+CRANRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) + "' in " +
+ stringify(name()) + ":");
+
+ need_packages();
+
+ if (! do_has_category_named(q.category))
+ return false;
+
+ return _imp->package_names.end() != _imp->package_names.find(q);
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+CRANRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ result->insert(CategoryNamePart("cran"));
+
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+CRANRepository::do_package_names(const CategoryNamePart & c) const
+{
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ need_packages();
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ if (! do_has_category_named(c))
+ return result;
+
+ PackagesMap::const_iterator n(_imp->package_names.begin()), n_end(_imp->package_names.end());
+ for ( ; n != n_end ; ++n)
+ result->insert(n->first);
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+CRANRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ need_packages();
+
+ std::tr1::shared_ptr<VersionSpecCollection> result(new VersionSpecCollection::Concrete);
+ if (_imp->version_specs.end() != _imp->version_specs.find(n))
+ result->insert(_imp->version_specs.find(n)->second);
+
+ return result;
+}
+
+bool
+CRANRepository::do_has_version(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When checking for version '" + stringify(v) + "' in '"
+ + stringify(q) + "' in " + stringify(name()) + ":");
+
+ need_packages();
+
+ if (has_package_named(q))
+ return v == _imp->version_specs.find(q)->second;
+ else
+ return false;
+}
+
+void
+CRANRepository::need_packages() const
+{
+ if (_imp->has_packages)
+ return;
+
+ Context context("When loading category names for " + stringify(name()) + ":");
+
+ LineConfigFile packages(FSEntry(_imp->location / "PACKAGES"));
+ LineConfigFile::Iterator l(packages.begin()), l_end(packages.end());
+ std::string last_package_name;
+ bool skip_invalid_package = false;
+ for ( ; l != l_end ; ++l)
+ {
+ Context local_context("When parsing line '" + *l + "':");
+
+ std::string line(strip_leading(strip_trailing(*l, " \t"), " \t"));
+ if (line.empty())
+ continue;
+
+ std::string::size_type pos(line.find(':'));
+ if (std::string::npos == pos)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Broken line in PACKAGES file: '" + stringify(_imp->location / "PACKAGES") + "'");
+ continue;
+ }
+
+ std::string key(line.substr(0, pos)), value(line.substr(pos + 1));
+ key = strip_leading(strip_trailing(key, " \t"), " \t");
+ value = strip_leading(strip_trailing(value, " \t"), " \t");
+ if (("Package" != key) && (skip_invalid_package))
+ {
+ skip_invalid_package = false;
+ continue;
+ }
+
+ if ("Package" == key)
+ {
+ CRANDescription::normalise_name(value);
+ last_package_name = value;
+ QualifiedPackageName package_name(CategoryNamePart("cran"), PackageNamePart(last_package_name));
+ _imp->package_names[package_name] = true;
+ }
+ else if ("Version" == key)
+ {
+ QualifiedPackageName package_name(CategoryNamePart("cran"), PackageNamePart(last_package_name));
+ CRANDescription::normalise_version(value);
+ VersionSpec version(value);
+ if (false == _imp->version_specs.insert(VersionsMap::value_type(package_name, version)).second)
+ {
+ skip_invalid_package = true;
+ Log::get_instance()->message(ll_warning, lc_context, "Multiple versions for package '"
+ + last_package_name + "'.");
+ continue;
+ }
+ }
+ else if ("Contains" == key)
+ {
+ std::list<std::string> contains;
+ WhitespaceTokeniser::get_instance()->tokenise(value, std::back_inserter(contains));
+ std::list<std::string>::const_iterator i(contains.begin()), i_end(contains.end());
+ // load metadata immediately
+ for ( ; i != i_end ; ++i)
+ {
+ Context c("When processing 'Contains:' line: '" + stringify(*i) + "':");
+ if (*i == last_package_name)
+ continue;
+
+ CRANDescription d(*i, FSEntry(_imp->location / std::string(last_package_name + ".DESCRIPTION")), false);
+
+ std::string dep(d.metadata->deps_interface->build_depend_string);
+ std::string pkg(d.metadata->cran_interface->package);
+ if ("" == dep)
+ dep = pkg;
+ else
+ dep += "," + pkg;
+ d.metadata->deps_interface->build_depend_string = dep;
+ d.metadata->cran_interface->is_bundle_member = true;
+
+ _imp->package_names[d.name] = true;
+ _imp->metadata.insert(std::make_pair(std::make_pair(d.name, d.version), d.metadata));
+ _imp->version_specs.insert(VersionsMap::value_type(d.name, d.version));
+ }
+ }
+ }
+
+ _imp->has_packages = true;
+}
+
+RepositoryName
+CRANRepository::fetch_repo_name(const std::string & location)
+{
+ std::string modified_location(FSEntry(location).basename());
+ std::replace(modified_location.begin(), modified_location.end(), '/', '-');
+ return RepositoryName("cran-" + modified_location);
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+CRANRepository::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (_imp->metadata.end() != _imp->metadata.find(
+ std::make_pair(q, v)))
+ return _imp->metadata.find(std::make_pair(q, v))->second;
+
+ Context context("When fetching metadata for " + stringify(q) +
+ "-" + stringify(v));
+
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ std::tr1::shared_ptr<VersionMetadata> result(new CRANVersionMetadata(false));
+
+ FSEntry d(_imp->location);
+ PackageNamePart p(q.package);
+ std::string n(stringify(p));
+ CRANDescription::denormalise_name(n);
+ d /= n + ".DESCRIPTION";
+
+ if (d.is_regular_file())
+ {
+ CRANDescription desc(stringify(p), d, false);
+ result = desc.metadata;
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "has_version failed for request for '" +
+ stringify(q) + "-" + stringify(v) + "' in repository '" +
+ stringify(name()) + "': File '" + n + ".DESCRIPTION' not present.");
+ result.reset(new CRANVersionMetadata(false));
+ result->eapi = "UNKNOWN";
+ }
+
+ _imp->metadata.insert(std::make_pair(std::make_pair(q, v), result));
+ return result;
+}
+
+std::tr1::shared_ptr<Repository>
+CRANRepository::make_cran_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ Context context("When making CRAN repository from repo_file '" +
+ (m->end() == m->find("repo_file") ? std::string("?") : m->find("repo_file")->second) + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw CRANRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string library;
+ if (m->end() == m->find("library") || ((library = m->find("library")->second)).empty())
+ throw CRANRepositoryConfigurationError("Key 'library' not specified or empty");
+
+ std::string distdir;
+ if (m->end() == m->find("distdir") || ((distdir = m->find("distdir")->second)).empty())
+ distdir = location + "/distfiles";
+
+ std::string mirror;
+ if (m->end() == m->find("mirror") || ((mirror = m->find("mirror")->second)).empty())
+ mirror = "http://cran.r-project.org/";
+
+ std::string sync;
+ if (m->end() == m->find("sync") || ((sync = m->find("sync")->second)).empty())
+ sync = "rsync://cran.r-project.org/CRAN";
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = "/var/tmp/paludis";
+
+ std::string root;
+ if (m->end() == m->find("root") || ((root = m->find("root")->second)).empty())
+ root = "/";
+
+ return std::tr1::shared_ptr<Repository>(new CRANRepository(CRANRepositoryParams::create()
+ .environment(env)
+ .location(location)
+ .distdir(distdir)
+ .sync(sync)
+ .buildroot(buildroot)
+ .root(root)
+ .library(library)
+ .mirror(mirror)));
+}
+
+CRANRepositoryConfigurationError::CRANRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("CRAN repository configuration error: " + msg)
+{
+}
+
+bool
+CRANRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+CRANRepository::do_install(const QualifiedPackageName &q, const VersionSpec &vn,
+ const InstallOptions &o) const
+{
+ PackageNamePart pn(q.package);
+ CategoryNamePart c("cran");
+ std::tr1::shared_ptr<const VersionMetadata> vm(do_version_metadata(q, vn));
+
+ if (vm->cran_interface->is_bundle_member)
+ {
+ MakeEnvCommand cmd(LIBEXECDIR "/paludis/cran.bash skip", "");
+ cmd = cmd("CATEGORY", "cran");
+ cmd = cmd("PN", stringify(pn));
+ cmd = cmd("PV", stringify(vn));
+ return;
+ }
+
+ std::string p(vm->cran_interface->package);
+ std::string v(vm->cran_interface->version);
+
+ MakeEnvCommand cmd(LIBEXECDIR "/paludis/cran.bash fetch", "");
+ cmd = cmd("CATEGORY", "cran");
+ cmd = cmd("DISTDIR", stringify(_imp->distdir));
+ cmd = cmd("DISTFILE", std::string(p + "_" + v + ".tar.gz"));
+ cmd = cmd("PN", stringify(pn));
+ cmd = cmd("PV", stringify(vn));
+ cmd = cmd("PALUDIS_CRAN_MIRRORS", _imp->mirror);
+ cmd = cmd("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"));
+ cmd = cmd("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()));
+ cmd = cmd("PALUDIS_BASHRC_FILES", _imp->env->bashrc_files());
+
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't fetch sources for '" + stringify(q) + "-" + stringify(vn) + "'");
+
+ if (o.fetch_only)
+ return;
+
+ std::string image(stringify(_imp->buildroot / stringify(q) / "image"));
+ std::string workdir(stringify(_imp->buildroot / stringify(q) / "work"));
+
+ cmd = MakeEnvCommand(make_sandbox_command(LIBEXECDIR "/paludis/cran.bash clean install"), "");
+ cmd = cmd("CATEGORY", "cran");
+ cmd = cmd("DISTDIR", stringify(_imp->distdir));
+ cmd = cmd("DISTFILE", std::string(p + "_" + v + ".tar.gz"));
+ cmd = cmd("IMAGE", image);
+ cmd = cmd("IS_BUNDLE", (vm->cran_interface->is_bundle ? "yes" : ""));
+ cmd = cmd("LOCATION", stringify(_imp->location));
+ cmd = cmd("PN", stringify(pn));
+ cmd = cmd("PV", stringify(vn));
+ cmd = cmd("PALUDIS_CRAN_LIBRARY", stringify(_imp->library));
+ cmd = cmd("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"));
+ cmd = cmd("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()));
+ cmd = cmd("PALUDIS_BASHRC_FILES", _imp->env->bashrc_files());
+ cmd = cmd("ROOT", stringify(_imp->root));
+ cmd = cmd("WORKDIR", workdir);
+
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't install '" + stringify(q) + "-" + stringify(vn) + "' to '" +
+ image + "'");
+
+ cmd = MakeEnvCommand(LIBEXECDIR "/paludis/cran.bash merge clean", "");
+ cmd = cmd("IMAGE", image);
+ cmd = cmd("PN", p);
+ cmd = cmd("PV", stringify(vn));
+ cmd = cmd("PALUDIS_CRAN_LIBRARY", stringify(_imp->library));
+ cmd = cmd("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"));
+ cmd = cmd("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()));
+ cmd = cmd("PALUDIS_BASHRC_FILES", _imp->env->bashrc_files());
+ cmd = cmd("ROOT", stringify(_imp->root));
+ cmd = cmd("WORKDIR", workdir);
+ cmd = cmd("REPOSITORY", stringify(name()));
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't merge '" + stringify(q) + "-" + stringify(vn) + "' to '" +
+ stringify(_imp->root) + "'");
+
+ return;
+}
+
+std::tr1::shared_ptr<DepAtom>
+CRANRepository::do_package_set(const SetName & s) const
+{
+ if ("base" == s.data())
+ {
+ /**
+ * \todo Implement system as all package which are installed
+ * by dev-lang/R by default.
+ */
+ return std::tr1::shared_ptr<AllDepAtom>(new AllDepAtom);
+ }
+ else
+ return std::tr1::shared_ptr<DepAtom>();
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+CRANRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ std::tr1::shared_ptr<SetsCollection> result(new SetsCollection::Concrete);
+ result->insert(SetName("base"));
+ return result;
+}
+
+bool
+CRANRepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+
+ std::string cmd("rsync --delete --recursive --progress --exclude \"*.html\" --exclude \"*.INDEX\" '" +
+ _imp->sync + "/src/contrib/Descriptions/' ./");
+
+ if (0 != run_command_in_directory(cmd, _imp->location))
+ return false;
+
+ cmd = "rsync --progress '" + _imp->sync + "/src/contrib/PACKAGES' ./";
+
+ if (0 != run_command_in_directory(cmd, _imp->location))
+ return false;
+
+ cmd = "rsync --progress '" + _imp->sync + "/CRAN_mirrors.csv' ./";
+
+ return 0 == run_command_in_directory(cmd, _imp->location);
+}
+
+void
+CRANRepository::invalidate()
+{
+ _imp.reset(new Implementation<CRANRepository>(_imp->params));
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_repository.hh b/0.18.0/paludis/repositories/cran/cran_repository.hh
new file mode 100644
index 000000000..4bfa4a52e
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_repository.hh
@@ -0,0 +1,132 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_CRAN_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <string>
+
+/** \file
+ * Declaration for the CRANRepository class.
+ *
+ * \ingroup grpcranrepository
+ */
+
+namespace paludis
+{
+ class PackageDatabase;
+
+#include <paludis/repositories/cran/cran_repository-sr.hh>
+
+ /**
+ * A CRANRepository is a Repository that handles the layout used by
+ * the GNU R project for the Comprehensive R Archive Network
+ *
+ * \ingroup grpcranrepository
+ */
+ class PALUDIS_VISIBLE CRANRepository :
+ public Repository,
+ public RepositoryInstallableInterface,
+ public RepositorySyncableInterface,
+ public RepositorySetsInterface,
+ private PrivateImplementationPattern<CRANRepository>
+ {
+ private:
+ void need_packages() const;
+ void need_version_names(const QualifiedPackageName &) const;
+ void need_virtual_names() const;
+
+ protected:
+ /**
+ * Try to get the repository name for a particular repository.
+ */
+ static RepositoryName fetch_repo_name(const std::string & location);
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual std::tr1::shared_ptr<DepAtom> do_package_set(const SetName &) const;
+
+ virtual std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+
+ virtual bool do_sync() const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ CRANRepository(const CRANRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static std::tr1::shared_ptr<Repository> make_cran_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m);
+
+ /**
+ * Destructor.
+ */
+ virtual ~CRANRepository();
+
+ virtual void invalidate();
+ };
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * CRANRepository::make_cran_repository.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE CRANRepositoryConfigurationError : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ CRANRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/cran/cran_repository.sr b/0.18.0/paludis/repositories/cran/cran_repository.sr
new file mode 100644
index 000000000..b0466cc74
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_repository.sr
@@ -0,0 +1,27 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_CRANRepositoryParams()
+{
+ key environment "const Environment *"
+ key location FSEntry
+ key distdir FSEntry
+ key mirror std::string
+ key sync std::string
+ key buildroot FSEntry
+ key root FSEntry
+ key library FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a CRANRepository
+ *
+ * \see CRANRepository
+ * \ingroup grpcranrepository
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_repository_TEST.cc b/0.18.0/paludis/repositories/cran/cran_repository_TEST.cc
new file mode 100644
index 000000000..40bdb6a23
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_repository_TEST.cc
@@ -0,0 +1,97 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/dep_atom.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_description.hh>
+#include <paludis/repositories/cran/cran_repository.hh>
+#include <paludis/environment/test/test_environment.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/system.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+/** \file
+ * Test cases for CRANRepository.
+ *
+ * \ingroup grptestcases
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test CRANRepository to parse a well formed PACKAGES file.
+ *
+ * \ingroup grptestcases
+ */
+ struct CRANRepositoryPackagesTest : TestCase
+ {
+ CRANRepositoryPackagesTest() : TestCase("PACKAGES") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "cran");
+ keys->insert("library", "cran_repository_TEST_dir/library");
+ keys->insert("location", "cran_repository_TEST_dir/repo1");
+ keys->insert("buildroot", "cran_repository_TEST_dir/tmp");
+ std::tr1::shared_ptr<Repository> repo(CRANRepository::make_cran_repository(
+ &env, keys));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cran")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/testpackage1")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/testpackage2")));
+ }
+ } test_cran_repository_packages;
+
+ /**
+ * \test Test CRANRepository to handly 'Bundle:'s correctly.
+ *
+ * \ingroup grptestcases
+ */
+ struct CRANRepositoryBundleTest: TestCase
+ {
+ CRANRepositoryBundleTest() : TestCase("Bundle") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "cran");
+ keys->insert("library", "cran_repository_TEST_dir/library");
+ keys->insert("location", "cran_repository_TEST_dir/repo2");
+ keys->insert("buildroot", "cran_repository_TEST_dir/tmp");
+ std::tr1::shared_ptr<Repository> repo(CRANRepository::make_cran_repository(
+ &env, keys));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/testbundle")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/bundlepkg1")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/bundlepkg2")));
+ }
+ } test_cran_repository_bundle;
+
+ /** \todo in repo1
+ * \todo test case for DESCRIPTION files
+ */
+}
diff --git a/0.18.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh b/0.18.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..d30492240
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d cran_repository_TEST_dir ] ; then
+ rm -fr cran_repository_TEST_dir
+else
+ true
+fi
diff --git a/0.18.0/paludis/repositories/cran/cran_repository_TEST_setup.sh b/0.18.0/paludis/repositories/cran/cran_repository_TEST_setup.sh
new file mode 100755
index 000000000..93fdbee71
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_repository_TEST_setup.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir cran_repository_TEST_dir || exit 1
+cd cran_repository_TEST_dir || exit 1
+
+# repo1
+mkdir -p repo1
+cat <<EOF >> repo1/PACKAGES
+Package: testpackage1
+Version: 2006.05.08
+Title: Test on a well formed PACKAGES file
+Depends: R (>= 2.0.0)
+
+
+Package: testpackage2
+Version: 2006.05.08
+Title: Test on a well formed PACKAGES file
+EOF
+cat <<EOF >> repo1/testpackage1.DESCRIPTION
+Package: testpackage1
+Version: 2006.05.08
+Title: Test on a well formed PACKAGES file
+Depends: R (>= 2.0.0)
+Description: This description
+ spans
+ multiple lines without
+ trailing backslashes or leading tabs :-/
+License: Some weirdo license string
+Packaged: Mon May 08 12:00:00 2006; kugelfang
+EOF
+cat <<EOF >> repo1/testpackage2.DESCRIPTION
+Package: testpackage2
+Version: 1
+Title: 2nd Test Packages
+Depends: R, testpackage1
+License: Another weirdo license string
+Packaged: Mon May 08 22:00:00 2006; kugelfang
+EOF
+
+mkdir -p repo2
+cat <<EOF >> repo2/PACKAGES
+Package: testbundle
+Version: 1
+Title: Testbundle for bundlepkg1 and bundlepkg2
+Bundle: testbundle
+Contains: bundlepkg1 bundlepkg2
+EOF
+cat <<EOF >> repo2/testbundle.DESCRIPTION
+Bundle: testbundle
+Version: 1
+Date: 21 May 2006
+Title: Testbundle for bundlepkg1 and bundlepkg2
+Contains: bundlepkg1 bundlepkg2
+License: Weird obfuscation of GPL
+Packaged: Sun May 21 12:34:56 2006; kugelfang
+EOF
diff --git a/0.18.0/paludis/repositories/cran/cran_version_metadata.cc b/0.18.0/paludis/repositories/cran/cran_version_metadata.cc
new file mode 100644
index 000000000..c110697e2
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_version_metadata.cc
@@ -0,0 +1,47 @@
+/* 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 "cran_version_metadata.hh"
+#include "cran_dep_parser.hh"
+
+using namespace paludis;
+
+CRANVersionMetadata::CRANVersionMetadata(bool want_origins) :
+ VersionMetadata(
+ VersionMetadataBase(SlotName("unset"), "", "", "UNKNOWN"),
+ VersionMetadataCapabilities::create()
+ .cran_interface(this)
+ .ebuild_interface(0)
+ .license_interface(0)
+ .virtual_interface(0)
+ .origins_interface(want_origins ? _origins : 0)
+ .deps_interface(this)
+ ),
+ VersionMetadataCRANInterface("", "", "", false, false),
+ VersionMetadataDepsInterface(CRANDepParser::parse),
+ _origins(want_origins ? new VersionMetadataOriginsInterface : 0)
+{
+}
+
+CRANVersionMetadata::~CRANVersionMetadata()
+{
+ if (_origins)
+ delete _origins;
+}
+
diff --git a/0.18.0/paludis/repositories/cran/cran_version_metadata.hh b/0.18.0/paludis/repositories/cran/cran_version_metadata.hh
new file mode 100644
index 000000000..f7bc9ba01
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/cran_version_metadata.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_CRAN_CRAN_VERSION_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_CRAN_CRAN_VERSION_METADATA_HH 1
+
+#include <paludis/version_metadata.hh>
+
+namespace paludis
+{
+ class CRANVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataCRANInterface,
+ public VersionMetadataDepsInterface
+ {
+ private:
+ VersionMetadataOriginsInterface * _origins;
+
+ public:
+ CRANVersionMetadata(bool want_origins);
+ virtual ~CRANVersionMetadata();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/cran/registration.cc b/0.18.0/paludis/repositories/cran/registration.cc
new file mode 100644
index 000000000..30182ec2f
--- /dev/null
+++ b/0.18.0/paludis/repositories/cran/registration.cc
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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/cran/cran_repository.hh>
+#include <paludis/repositories/cran/cran_installed_repository.hh>
+#include "config.h"
+
+using namespace paludis;
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("cran", &CRANRepository::make_cran_repository);
+ maker->register_maker("cran_installed", &CRANInstalledRepository::make_cran_installed_repository);
+}
+
+#endif
+
+
diff --git a/0.18.0/paludis/repositories/fake/Makefile.am b/0.18.0/paludis/repositories/fake/Makefile.am
new file mode 100644
index 000000000..dcc3eeb53
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/Makefile.am
@@ -0,0 +1,45 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludisfakerepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisfakerepository.la
+
+endif
+
+libpaludisfakerepository_la_SOURCES = \
+ fake_repository_base.cc fake_repository_base.hh \
+ fake_repository.cc fake_repository.hh \
+ fake_installed_repository.cc fake_installed_repository.hh
+
+if ! MONOLITHIC
+
+libpaludisfakerepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la
+
+endif
+
+libpaludisfakerepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_fake_includedir = $(includedir)/paludis/repositories/fake/
+paludis_repositories_fake_include_HEADERS = \
+ fake_repository.hh \
+ fake_repository_base.hh \
+ fake_installed_repository.hh
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/0.18.0/paludis/repositories/fake/fake_installed_repository.cc b/0.18.0/paludis/repositories/fake/fake_installed_repository.cc
new file mode 100644
index 000000000..c39566595
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/fake_installed_repository.cc
@@ -0,0 +1,106 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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 "fake_installed_repository.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/dep_atom_flattener.hh>
+
+using namespace paludis;
+
+FakeInstalledRepository::FakeInstalledRepository(const Environment * const e, const RepositoryName & our_name) :
+ FakeRepositoryBase(e, our_name, RepositoryCapabilities::create()
+ .installable_interface(0)
+ .installed_interface(this)
+ .contents_interface(0)
+ .mask_interface(this)
+ .news_interface(0)
+ .sets_interface(this)
+ .syncable_interface(0)
+ .uninstallable_interface(0)
+ .use_interface(this)
+ .world_interface(0)
+ .mirrors_interface(0)
+ .environment_variable_interface(0)
+ .provides_interface(this)
+ .virtuals_interface(0)
+ .config_interface(0)
+ .destination_interface(this),
+ "fake_installed")
+{
+}
+
+bool
+FakeInstalledRepository::is_suitable_destination_for(const PackageDatabaseEntry &) const
+{
+ return true;
+}
+
+std::tr1::shared_ptr<const FakeInstalledRepository::ProvidesCollection>
+FakeInstalledRepository::provided_packages() const
+{
+ std::tr1::shared_ptr<ProvidesCollection> result(new ProvidesCollection::Concrete);
+
+ std::tr1::shared_ptr<const CategoryNamePartCollection> cats(category_names());
+ for (CategoryNamePartCollection::Iterator c(cats->begin()), c_end(cats->end()) ;
+ c != c_end ; ++c)
+ {
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> pkgs(package_names(*c));
+ for (QualifiedPackageNameCollection::Iterator p(pkgs->begin()), p_end(pkgs->end()) ;
+ p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<const VersionSpecCollection> vers(version_specs(*p));
+ for (VersionSpecCollection::Iterator v(vers->begin()), v_end(vers->end()) ;
+ v != v_end ; ++v)
+ {
+ std::tr1::shared_ptr<const VersionMetadata> m(version_metadata(*p, *v));
+ if (! m->ebuild_interface)
+ continue;
+
+ std::tr1::shared_ptr<const DepAtom> provide(PortageDepParser::parse(m->ebuild_interface->provide_string,
+ PortageDepParserPolicy<PackageDepAtom, false>::get_instance()));
+ PackageDatabaseEntry dbe(*p, *v, name());
+ DepAtomFlattener f(environment(), &dbe, provide);
+
+ for (DepAtomFlattener::Iterator q(f.begin()), q_end(f.end()) ; q != q_end ; ++q)
+ result->insert(RepositoryProvidesEntry::create()
+ .virtual_name(QualifiedPackageName((*q)->text()))
+ .version(*v)
+ .provided_by_name(*p));
+ }
+ }
+ }
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+FakeInstalledRepository::provided_package_version_metadata(const RepositoryProvidesEntry & p) const
+{
+ std::tr1::shared_ptr<const VersionMetadata> m(version_metadata(p.provided_by_name, p.version));
+ std::tr1::shared_ptr<FakeVirtualVersionMetadata> result(new FakeVirtualVersionMetadata(
+ m->slot, PackageDatabaseEntry(p.provided_by_name, p.version, name())));
+
+ result->eapi = m->eapi;
+ result->deps_interface->build_depend_string = stringify(p.provided_by_name);
+ result->deps_interface->run_depend_string = stringify(p.provided_by_name);
+
+ return result;
+}
+
diff --git a/0.18.0/paludis/repositories/fake/fake_installed_repository.hh b/0.18.0/paludis/repositories/fake/fake_installed_repository.hh
new file mode 100644
index 000000000..ba14379ec
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/fake_installed_repository.hh
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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_FAKE_FAKE_INSTALLED_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_FAKE_FAKE_INSTALLED_REPOSITORY_HH 1
+
+#include <paludis/repositories/fake/fake_repository_base.hh>
+
+namespace paludis
+{
+ /**
+ * A fake repository for test cases, for installed packages.
+ *
+ * \ingroup grpfakerepository
+ */
+ class PALUDIS_VISIBLE FakeInstalledRepository :
+ public FakeRepositoryBase,
+ public RepositoryInstalledInterface,
+ public RepositoryDestinationInterface,
+ public RepositoryProvidesInterface
+ {
+ protected:
+ virtual std::tr1::shared_ptr<const ProvidesCollection> provided_packages() const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> provided_package_version_metadata(
+ const RepositoryProvidesEntry &) const;
+
+ public:
+ FakeInstalledRepository(const Environment * const, const RepositoryName &);
+
+ bool is_suitable_destination_for(const PackageDatabaseEntry &) const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/fake/fake_repository.cc b/0.18.0/paludis/repositories/fake/fake_repository.cc
new file mode 100644
index 000000000..d5ca05880
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/fake_repository.cc
@@ -0,0 +1,99 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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 "fake_repository.hh"
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/portage_dep_parser.hh>
+
+using namespace paludis;
+
+FakeRepository::FakeRepository(const Environment * const e, const RepositoryName & our_name) :
+ FakeRepositoryBase(e, our_name, RepositoryCapabilities::create()
+ .installable_interface(this)
+ .installed_interface(0)
+ .contents_interface(0)
+ .mask_interface(this)
+ .news_interface(0)
+ .sets_interface(this)
+ .syncable_interface(0)
+ .uninstallable_interface(0)
+ .use_interface(this)
+ .world_interface(0)
+ .mirrors_interface(0)
+ .environment_variable_interface(0)
+ .provides_interface(0)
+ .virtuals_interface(this)
+ .config_interface(0)
+ .destination_interface(0),
+ "fake"),
+ _virtual_packages(new VirtualsCollection::Concrete)
+{
+}
+
+void
+FakeRepository::do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const
+{
+}
+
+std::tr1::shared_ptr<const FakeRepository::VirtualsCollection>
+FakeRepository::virtual_packages() const
+{
+ return _virtual_packages;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+FakeRepository::virtual_package_version_metadata(
+ const RepositoryVirtualsEntry & p, const VersionSpec & v) const
+{
+ std::tr1::shared_ptr<const VersionMetadata> m(version_metadata(p.provided_by_atom->package(), v));
+ std::tr1::shared_ptr<FakeVirtualVersionMetadata> result(new FakeVirtualVersionMetadata(
+ m->slot, PackageDatabaseEntry(p.provided_by_atom->package(), v, name())));
+
+ result->eapi = m->eapi;
+ result->deps_interface->build_depend_string = "=" + stringify(p.provided_by_atom->package()) + "-" + stringify(v);
+ result->deps_interface->run_depend_string = "=" + stringify(p.provided_by_atom->package()) + "-" + stringify(v);
+
+ return result;
+}
+
+void
+FakeRepository::add_virtual_package(const QualifiedPackageName & q, std::tr1::shared_ptr<const PackageDepAtom> p)
+{
+ _virtual_packages->insert(RepositoryVirtualsEntry(q, p));
+}
+
+#ifndef MONOLITHIC
+
+namespace paludis
+{
+ class RepositoryMaker;
+}
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker *)
+{
+}
+
+#endif
+
diff --git a/0.18.0/paludis/repositories/fake/fake_repository.hh b/0.18.0/paludis/repositories/fake/fake_repository.hh
new file mode 100644
index 000000000..02fc2715f
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/fake_repository.hh
@@ -0,0 +1,56 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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_FAKE_FAKE_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_FAKE_FAKE_REPOSITORY_HH 1
+
+#include <paludis/repositories/fake/fake_repository_base.hh>
+
+namespace paludis
+{
+ /**
+ * Fake repository for use in test cases.
+ *
+ * \ingroup grpfakerepository
+ */
+ class PALUDIS_VISIBLE FakeRepository :
+ public FakeRepositoryBase,
+ public RepositoryInstallableInterface,
+ public RepositoryVirtualsInterface
+ {
+ private:
+ std::tr1::shared_ptr<VirtualsCollection> _virtual_packages;
+
+ protected:
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual std::tr1::shared_ptr<const VirtualsCollection> virtual_packages() const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> virtual_package_version_metadata(
+ const RepositoryVirtualsEntry &, const VersionSpec & v) const;
+
+ public:
+ FakeRepository(const Environment * const, const RepositoryName &);
+
+ void add_virtual_package(const QualifiedPackageName &, std::tr1::shared_ptr<const PackageDepAtom>);
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/fake/fake_repository_base.cc b/0.18.0/paludis/repositories/fake/fake_repository_base.cc
new file mode 100644
index 000000000..7a162f6f4
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/fake_repository_base.cc
@@ -0,0 +1,346 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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 <map>
+#include <paludis/repositories/fake/fake_repository_base.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/version_metadata.hh>
+#include <paludis/portage_dep_parser.hh>
+
+/** \file
+ * Implementation for FakeRepositoryBase.
+ *
+ * \ingroup grpfakerepository
+ */
+
+using namespace paludis;
+
+namespace paludis
+{
+ /**
+ * Implementation data for FakeRepositoryBase.
+ *
+ * \ingroup grpfakerepository
+ */
+ template<>
+ struct Implementation<FakeRepositoryBase> :
+ private InstantiationPolicy<Implementation<FakeRepositoryBase>, instantiation_method::NonCopyableTag>
+ {
+ /// Our category names.
+ std::tr1::shared_ptr<CategoryNamePartCollection> category_names;
+
+ /// Our package names.
+ std::map<CategoryNamePart, std::tr1::shared_ptr<PackageNamePartCollection> > package_names;
+
+ /// Our versions.
+ std::map<QualifiedPackageName, std::tr1::shared_ptr<VersionSpecCollection> > versions;
+
+ /// Our metadata.
+ std::map<std::string, std::tr1::shared_ptr<VersionMetadata> > metadata;
+
+ /// Our sets.
+ std::map<SetName, std::tr1::shared_ptr<DepAtom> > sets;
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ const Environment * const env;
+
+ /// Constructor.
+ Implementation(const Environment * const);
+ };
+
+ Implementation<FakeRepositoryBase>::Implementation(const Environment * const e) :
+ category_names(new CategoryNamePartCollection::Concrete),
+ env(e)
+ {
+ }
+}
+
+FakeRepositoryBase::FakeRepositoryBase(const Environment * const e,
+ const RepositoryName & our_name, const RepositoryCapabilities & caps,
+ const std::string & f) :
+ Repository(our_name, caps, f),
+ RepositoryMaskInterface(),
+ RepositoryUseInterface(),
+ PrivateImplementationPattern<FakeRepositoryBase>(new Implementation<FakeRepositoryBase>(e))
+{
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+ config_info->add_kv("format", "fake");
+
+ _info->add_section(config_info);
+}
+
+FakeRepositoryBase::~FakeRepositoryBase()
+{
+}
+
+bool
+FakeRepositoryBase::do_has_category_named(const CategoryNamePart & c) const
+{
+ return (_imp->category_names->end() != _imp->category_names->find(c));
+}
+
+bool
+FakeRepositoryBase::do_has_package_named(const QualifiedPackageName & q) const
+{
+ return has_category_named(q.category) &&
+ (_imp->package_names.find(q.category)->second->end() !=
+ _imp->package_names.find(q.category)->second->find(q.package));
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+FakeRepositoryBase::do_category_names() const
+{
+ return _imp->category_names;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+FakeRepositoryBase::do_package_names(const CategoryNamePart & c) const
+{
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ if (! has_category_named(c))
+ return result;
+
+ PackageNamePartCollection::Iterator p(_imp->package_names.find(c)->second->begin()),
+ p_end(_imp->package_names.find(c)->second->end());
+ for ( ; p != p_end ; ++p)
+ result->insert(c + *p);
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+FakeRepositoryBase::do_version_specs(const QualifiedPackageName & n) const
+{
+ if (! has_category_named(n.category))
+ return std::tr1::shared_ptr<VersionSpecCollection>(new VersionSpecCollection::Concrete);
+ if (! has_package_named(n))
+ return std::tr1::shared_ptr<VersionSpecCollection>(new VersionSpecCollection::Concrete);
+ return _imp->versions.find(n)->second;
+}
+
+bool
+FakeRepositoryBase::do_has_version(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_category_named(q.category))
+ return false;
+ if (! has_package_named(q))
+ return false;
+ return _imp->versions.find(q)->second->find(v) !=
+ _imp->versions.find(q)->second->end();
+}
+
+void
+FakeRepositoryBase::add_category(const CategoryNamePart & c)
+{
+ _imp->category_names->insert(c);
+ _imp->package_names.insert(std::make_pair(c, new PackageNamePartCollection::Concrete));
+}
+
+void
+FakeRepositoryBase::add_package(const QualifiedPackageName & q)
+{
+ add_category(q.category);
+ _imp->package_names.find(q.category)->second->insert(q.package);
+ _imp->versions.insert(std::make_pair(q, new VersionSpecCollection::Concrete));
+}
+
+std::tr1::shared_ptr<VersionMetadata>
+FakeRepositoryBase::add_version(const QualifiedPackageName & q, const VersionSpec & v)
+{
+ add_package(q);
+ _imp->versions.find(q)->second->insert(v);
+ _imp->metadata.insert(
+ std::make_pair(stringify(q) + "-" + stringify(v),
+ std::tr1::shared_ptr<VersionMetadata>(new FakeVersionMetadata)));
+ std::tr1::shared_ptr<VersionMetadata> r(_imp->metadata.find(stringify(q) + "-" + stringify(v))->second);
+ r->slot = SlotName("0");
+ r->eapi = "0";
+ return r;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+FakeRepositoryBase::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_version(q, v))
+ throw InternalError(PALUDIS_HERE, "no version");
+ return _imp->metadata.find(stringify(q) + "-" + stringify(v))->second;
+}
+
+bool
+FakeRepositoryBase::do_query_repository_masks(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+bool
+FakeRepositoryBase::do_query_profile_masks(const QualifiedPackageName &, const VersionSpec &) const
+{
+ return false;
+}
+
+UseFlagState
+FakeRepositoryBase::do_query_use(const UseFlagName &, const PackageDatabaseEntry *) const
+{
+ return use_unspecified;
+}
+
+bool
+FakeRepositoryBase::do_query_use_mask(const UseFlagName &, const PackageDatabaseEntry *) const
+{
+ return false;
+}
+
+bool
+FakeRepositoryBase::do_query_use_force(const UseFlagName &, const PackageDatabaseEntry *) const
+{
+ return false;
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+FakeRepositoryBase::do_arch_flags() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+bool
+FakeRepositoryBase::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+FakeRepositoryBase::invalidate()
+{
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+FakeRepositoryBase::do_use_expand_flags() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+FakeRepositoryBase::do_use_expand_hidden_prefixes() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+FakeRepositoryBase::do_use_expand_prefixes() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagName
+FakeRepositoryBase::do_use_expand_name(const UseFlagName & u) const
+{
+ return u;
+}
+
+UseFlagName
+FakeRepositoryBase::do_use_expand_value(const UseFlagName & u) const
+{
+ return u;
+}
+
+void
+FakeRepositoryBase::add_package_set(const SetName & n, std::tr1::shared_ptr<DepAtom> s)
+{
+ _imp->sets.insert(std::make_pair(n, s));
+}
+
+std::tr1::shared_ptr<DepAtom>
+FakeRepositoryBase::do_package_set(const SetName & id) const
+{
+ std::map<SetName, std::tr1::shared_ptr<DepAtom> >::const_iterator i(_imp->sets.find(id));
+ if (_imp->sets.end() == i)
+ return std::tr1::shared_ptr<DepAtom>();
+ else
+ return i->second;
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+FakeRepositoryBase::sets_list() const
+{
+ std::tr1::shared_ptr<SetsCollection> result(new SetsCollection::Concrete);
+ std::copy(_imp->sets.begin(), _imp->sets.end(),
+ transform_inserter(result->inserter(), SelectFirst<SetName, std::tr1::shared_ptr<DepAtom> >()));
+ return result;
+}
+
+std::string
+FakeRepositoryBase::do_describe_use_flag(const UseFlagName &,
+ const PackageDatabaseEntry * const) const
+{
+ return "";
+}
+
+const Environment *
+FakeRepositoryBase::environment() const
+{
+ return _imp->env;
+}
+
+FakeVersionMetadata::FakeVersionMetadata() :
+ VersionMetadata(
+ VersionMetadataBase(SlotName("0"), "", "", "paludis-1"),
+ VersionMetadataCapabilities::create()
+ .ebuild_interface(this)
+ .deps_interface(this)
+ .license_interface(this)
+ .cran_interface(0)
+ .virtual_interface(0)
+ .origins_interface(0)
+ ),
+ VersionMetadataEbuildInterface(),
+ VersionMetadataDepsInterface(&PortageDepParser::parse_depend),
+ VersionMetadataLicenseInterface(&PortageDepParser::parse_license)
+{
+ keywords = "test";
+}
+
+FakeVersionMetadata::~FakeVersionMetadata()
+{
+}
+
+FakeVirtualVersionMetadata::FakeVirtualVersionMetadata(const SlotName & s, const PackageDatabaseEntry & p) :
+ VersionMetadata(
+ VersionMetadataBase(s, "", "", "paludis-1"),
+ VersionMetadataCapabilities::create()
+ .ebuild_interface(0)
+ .deps_interface(this)
+ .license_interface(0)
+ .cran_interface(0)
+ .virtual_interface(this)
+ .origins_interface(0)
+ ),
+ VersionMetadataDepsInterface(&PortageDepParser::parse_depend),
+ VersionMetadataVirtualInterface(p)
+{
+}
+
+FakeVirtualVersionMetadata::~FakeVirtualVersionMetadata()
+{
+}
+
diff --git a/0.18.0/paludis/repositories/fake/fake_repository_base.hh b/0.18.0/paludis/repositories/fake/fake_repository_base.hh
new file mode 100644
index 000000000..4c415e5dd
--- /dev/null
+++ b/0.18.0/paludis/repositories/fake/fake_repository_base.hh
@@ -0,0 +1,186 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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_FAKE_REPOSITORY_BASE_HH
+#define PALUDIS_GUARD_PALUDIS_FAKE_REPOSITORY_BASE_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+/** \file
+ * Declarations for the FakeRepositoryBase class.
+ *
+ * \ingroup grpfakerepository
+ */
+
+namespace paludis
+{
+ /**
+ * FakeVersionMetadata is used by FakeRepository and
+ * FakeInstalledRepository for version metadata.
+ *
+ * \see FakeInstalledRepository
+ * \see FakeRepository
+ * \ingroup grpfakerepository
+ */
+ class FakeVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataEbuildInterface,
+ public VersionMetadataDepsInterface,
+ public VersionMetadataLicenseInterface
+ {
+ public:
+ FakeVersionMetadata();
+ virtual ~FakeVersionMetadata();
+ };
+
+ /**
+ * FakeVirtualVersionMetadata is used by FakeRepository for virtual
+ * version metadata.
+ *
+ * \see FakeRepository
+ * \ingroup grpfakerepository
+ */
+ class FakeVirtualVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataDepsInterface,
+ public VersionMetadataVirtualInterface
+ {
+ public:
+ FakeVirtualVersionMetadata(const SlotName &, const PackageDatabaseEntry &);
+ virtual ~FakeVirtualVersionMetadata();
+ };
+
+ /**
+ * A FakeRepositoryBase is a Repository subclass whose subclasses are used for
+ * various test cases.
+ *
+ * \see FakeRepository
+ * \see FakeInstalledRepository
+ * \ingroup grpfakerepository
+ */
+ class PALUDIS_VISIBLE FakeRepositoryBase :
+ public Repository,
+ public RepositoryMaskInterface,
+ public RepositoryUseInterface,
+ public RepositorySetsInterface,
+ private PrivateImplementationPattern<FakeRepositoryBase>
+ {
+ protected:
+ /* RepositoryUseInterface */
+
+ virtual UseFlagState do_query_use(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual bool do_query_use_mask(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual bool do_query_use_force(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_arch_flags() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_flags() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_hidden_prefixes() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_prefixes() const;
+ virtual UseFlagName do_use_expand_name(const UseFlagName & u) const;
+ virtual UseFlagName do_use_expand_value(const UseFlagName & u) const;
+ virtual std::string do_describe_use_flag(const UseFlagName &,
+ const PackageDatabaseEntry * const) const;
+
+ /* end of RepositoryUseInterface */
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_query_repository_masks(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_query_profile_masks(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual std::tr1::shared_ptr<DepAtom> do_package_set(const SetName & id) const;
+ virtual std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+
+ protected:
+ /**
+ * Constructor.
+ */
+ FakeRepositoryBase(const Environment * const env, const RepositoryName & name,
+ const RepositoryCapabilities & caps, const std::string &);
+
+ public:
+ /**
+ * Destructor.
+ */
+
+ ~FakeRepositoryBase();
+
+ /**
+ * Add a category.
+ */
+ void add_category(const CategoryNamePart &);
+
+ /**
+ * Add a package, and a category if necessary.
+ */
+ void add_package(const QualifiedPackageName &);
+
+ /**
+ * Add a version, and a package and category if necessary, and set some
+ * default values for its metadata, and return said metadata.
+ */
+ std::tr1::shared_ptr<VersionMetadata> add_version(
+ const QualifiedPackageName &, const VersionSpec &);
+
+ /**
+ * Add a version, and a package and category if necessary, and set some
+ * default values for its metadata, and return said metadata (convenience
+ * overload taking strings).
+ */
+ std::tr1::shared_ptr<VersionMetadata> add_version(
+ const std::string & c, const std::string & p, const std::string & v)
+ {
+ return add_version(CategoryNamePart(c) + PackageNamePart(p), VersionSpec(v));
+ }
+
+ /**
+ * Add a package set.
+ */
+ void add_package_set(const SetName &, std::tr1::shared_ptr<DepAtom>);
+
+ virtual void invalidate();
+
+ const Environment * environment() const;
+ };
+}
+
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/Makefile.am b/0.18.0/paludis/repositories/gems/Makefile.am
new file mode 100644
index 000000000..77461fb16
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/Makefile.am
@@ -0,0 +1,148 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+
+DISTCLEANFILES = \
+ gems_repository-sr.hh gems_repository-sr.cc \
+ cache-sr.hh cache-sr.cc
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludisgemsrepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisgemsrepository.la
+
+endif
+
+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 \
+ gems_repository-sr.hh \
+ gems_repository_exceptions.hh \
+ cache.hh \
+ cache-sr.hh \
+ make_gems_repository.hh \
+ yaml.hh \
+ gems_version_metadata.hh
+
+libpaludisgemsrepository_la_SOURCES = \
+ gems_repository.cc \
+ gems_repository_exceptions.cc \
+ cache.cc \
+ make_gems_repository.cc \
+ yaml.cc \
+ gems_version_metadata.cc \
+ registration.cc \
+ $(paludis_repositories_gems_include_HEADERS)
+
+if ! MONOLITHIC
+
+libpaludisgemsrepository_la_LIBADD = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ -lyaml \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+gems_repository_TEST_SOURCES = gems_repository_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/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a
+
+gems_repository_TEST_CXXFLAGS = -I$(top_srcdir)
+
+yaml_TEST_SOURCES = yaml_TEST.cc
+
+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/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a
+
+yaml_TEST_CXXFLAGS = -I$(top_srcdir)
+
+cache_TEST_SOURCES = cache_TEST.cc
+
+cache_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/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a
+
+cache_TEST_CXXFLAGS = -I$(top_srcdir)
+
+EXTRA_DIST = \
+ gems_repository_TEST.cc \
+ gems_repository_TEST_setup.sh \
+ gems_repository_TEST_cleanup.sh \
+ gems_repository.sr \
+ gems_repository-sr.hh \
+ gems_repository-sr.cc \
+ cache_TEST.cc \
+ cache_TEST_setup.sh \
+ cache_TEST_cleanup.sh \
+ cache.sr \
+ cache-sr.hh \
+ cache-sr.cc \
+ yaml_TEST.cc
+
+BUILT_SOURCES = \
+ gems_repository-sr.hh \
+ gems_repository-sr.cc \
+ cache-sr.hh \
+ cache-sr.cc
+
+check_SCRIPTS = \
+ gems_repository_TEST_setup.sh gems_repository_TEST_cleanup.sh \
+ cache_TEST_setup.sh cache_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(top_srcdir)/ebuild/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ LD_LIBRARY_PATH="`$(top_srcdir)/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/gems/`" \
+ bash $(top_srcdir)/test/run_test.sh
+
+TESTS = yaml_TEST gems_repository_TEST cache_TEST
+check_PROGRAMS = $(TESTS)
+
+gems_repository-sr.hh : gems_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/gems_repository.sr > $@
+
+gems_repository-sr.cc : gems_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/gems_repository.sr > $@
+
+cache-sr.hh : cache.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/cache.sr > $@
+
+cache-sr.cc : cache.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/cache.sr > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
diff --git a/0.18.0/paludis/repositories/gems/cache.cc b/0.18.0/paludis/repositories/gems/cache.cc
new file mode 100644
index 000000000..34bb33f09
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/cache.cc
@@ -0,0 +1,338 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "cache.hh"
+#include <paludis/repositories/gems/gems_repository_exceptions.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/save.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/log.hh>
+#include <list>
+
+#include <yaml.h>
+
+using namespace paludis;
+
+#include <paludis/repositories/gems/cache-sr.cc>
+
+namespace paludis
+{
+ template<>
+ struct Implementation<GemsCache>
+ {
+ std::list<GemsCacheEntry> entries;
+ };
+}
+
+namespace
+{
+ struct AsStringVisitor :
+ YamlNodeVisitorTypes::ConstVisitor
+ {
+ std::string str;
+ std::string join;
+
+ void visit(const YamlSequenceNode * nn)
+ {
+ if (join.empty())
+ throw GemsCacheError("Expected a scalar node, not a sequence");
+ else
+ std::for_each(nn->begin(), nn->end(), accept_visitor(this));
+ }
+
+ void visit(const YamlMappingNode *) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw GemsCacheError("Expected a scalar node, not a mapping");
+ }
+
+ void visit(const YamlScalarNode * nn)
+ {
+ if (! str.empty())
+ str.append(join);
+ str.append(nn->value());
+ }
+ };
+
+ std::string
+ as_string(std::tr1::shared_ptr<const YamlNode> n, const std::string & join = "")
+ {
+ AsStringVisitor v;
+ v.join = join;
+ n->accept(&v);
+ return v.str;
+ }
+
+ struct VersionVisitor :
+ YamlNodeVisitorTypes::ConstVisitor
+ {
+ std::string str;
+
+ void visit(const YamlScalarNode * n) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw GemsCacheError("Expected a mapping node, not scalar '" + n->value() + "'");
+ }
+
+ void visit(const YamlSequenceNode *) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw GemsCacheError("Expected a mapping node, not a sequence");
+ }
+
+ void visit(const YamlMappingNode * n)
+ {
+ Context context("When looking for a version: key in a mapping:");
+ for (YamlMappingNode::Iterator i(n->begin()), i_end(n->end()) ; i != i_end ; ++i)
+ if (i->first->value() == "version")
+ str = as_string(i->second);
+ }
+ };
+
+ struct RequirementsVisitor :
+ YamlNodeVisitorTypes::ConstVisitor
+ {
+ std::tr1::shared_ptr<VersionRequirements> r;
+ bool top_level;
+
+ std::string op;
+ std::string v;
+
+ RequirementsVisitor(std::tr1::shared_ptr<VersionRequirements> rr) :
+ r(rr),
+ top_level(true)
+ {
+ }
+
+ void visit(const YamlMappingNode * n)
+ {
+ Context context("When handling mapping node:");
+
+ if (top_level)
+ {
+ for (YamlMappingNode::Iterator i(n->begin()), i_end(n->end()) ; i != i_end ; ++i)
+ if (i->first->value() == "requirements")
+ {
+ Context context2("When handling mapping node requirements key:");
+ i->second->accept(this);
+ }
+ }
+ else
+ for (YamlMappingNode::Iterator i(n->begin()), i_end(n->end()) ; i != i_end ; ++i)
+ if (i->first->value() == "version")
+ {
+ Context local_context("When looking for a version: key in a requirements mapping:");
+ v = as_string(i->second);
+ }
+ }
+
+ void visit(const YamlSequenceNode * n)
+ {
+ Context context("When handling sequence node:");
+
+ if (top_level)
+ {
+ Save<bool> save_top_level(&top_level, false);
+ std::for_each(n->begin(), n->end(), accept_visitor(this));
+ }
+ else
+ {
+ op = "";
+ v = "";
+
+ YamlSequenceNode::Iterator i(n->begin()), i_end(n->end());
+ if (i == i_end)
+ throw YamlError("Expected a sequence with two entries, not zero");
+ op = as_string(*i++);
+ if (i == i_end)
+ throw YamlError("Expected a sequence with two entries, not one");
+ VersionVisitor vv;
+ (*i++)->accept(&vv);
+ v = vv.str;
+ if (i != i_end)
+ throw YamlError("Expected a sequence with two entries, not more than two");
+
+ r->push_back(VersionRequirement(VersionOperator(op), VersionSpec(v)));
+ }
+ }
+
+ void visit(const YamlScalarNode * n)
+ {
+ if (top_level && n->value().empty())
+ return;
+
+ throw YamlError("Didn't expect a scalar");
+ }
+ };
+
+ struct EntryVisitor :
+ YamlNodeVisitorTypes::ConstVisitor
+ {
+ const std::string id;
+
+ std::string name;
+ std::string version;
+ std::string summary;
+ std::string description;
+ std::string homepage;
+ std::tr1::shared_ptr<VersionRequirements> required_ruby_version;
+
+ EntryVisitor(const std::string & _id) :
+ id(_id),
+ required_ruby_version(new VersionRequirements::Concrete)
+ {
+ }
+
+ GemsCacheEntry
+ entry() const
+ {
+ Context context("When creating GemsCacheEntry with id '" + id + "':");
+
+ return GemsCacheEntry::create()
+ .name(PackageNamePart(name))
+ .version(VersionSpec(version))
+ .summary(summary)
+ .description(description)
+ .homepage(homepage)
+ .required_ruby_version(required_ruby_version)
+ .authors(std::tr1::shared_ptr<SequentialCollection<std::string> >())
+ .dependencies(std::tr1::shared_ptr<SequentialCollection<std::string> >())
+ .requirements(std::tr1::shared_ptr<SequentialCollection<std::string> >());
+ }
+
+ void visit(const YamlSequenceNode *) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw GemsCacheError("Sequence node not expected here'");
+ }
+
+ void visit(const YamlScalarNode * n) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw GemsCacheError("Node '" + n->value() + "' not expected here'");
+ }
+
+ void visit(const YamlMappingNode * n)
+ {
+ for (YamlMappingNode::Iterator i(n->begin()), i_end(n->end()) ; i != i_end ; ++i)
+ {
+ Context context("When handling entry key '" + i->first->value() + "':");
+
+ if (i->first->value() == "name")
+ name = as_string(i->second);
+ else if (i->first->value() == "summary")
+ summary = as_string(i->second);
+ else if (i->first->value() == "description")
+ description = as_string(i->second);
+ else if (i->first->value() == "homepage")
+ homepage = as_string(i->second, " ");
+ else if (i->first->value() == "version")
+ {
+ VersionVisitor v;
+ i->second->accept(&v);
+ version = v.str;
+ }
+ else if (i->first->value() == "required_ruby_version")
+ {
+ Context context2("When handling required_ruby_version children:");
+ RequirementsVisitor v(required_ruby_version);
+ i->second->accept(&v);
+ }
+ }
+ }
+ };
+
+ struct TopLevelVisitor :
+ YamlNodeVisitorTypes::ConstVisitor,
+ YamlNodeVisitorTypes::ConstVisitor::VisitChildren<TopLevelVisitor, YamlSequenceNode>
+ {
+ using YamlNodeVisitorTypes::ConstVisitor::VisitChildren<TopLevelVisitor, YamlSequenceNode>::visit;
+
+ Implementation<GemsCache> * imp;
+ bool top_level;
+
+ TopLevelVisitor(Implementation<GemsCache> * p) :
+ imp(p),
+ top_level(true)
+ {
+ }
+
+ void visit(const YamlMappingNode * n)
+ {
+ for (YamlMappingNode::Iterator i(n->begin()), i_end(n->end()) ; i != i_end ; ++i)
+ {
+ if (top_level)
+ {
+ if (i->first->value() != "gems")
+ throw GemsCacheError("Node '" + i->first->value() + "' is not 'gems'");
+ Save<bool> save_top_level(&top_level, false);
+ i->second->accept(this);
+ }
+ else
+ {
+ Context context("When processing ID '" + i->first->value() + "':");
+ try
+ {
+ EntryVisitor v(i->first->value());
+ i->second->accept(&v);
+ imp->entries.push_back(v.entry());
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_qa, lc_context, "Skipping ID '"
+ + i->first->value() + "' due to exception '" + e.message() + "' ("
+ + e.what() + ")");
+ }
+ }
+ }
+ }
+
+ void visit(const YamlScalarNode * n) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw GemsCacheError("Node '" + n->value() + "' not expected here'");
+ }
+ };
+}
+
+GemsCache::GemsCache(const FSEntry & loc) :
+ PrivateImplementationPattern<GemsCache>(new Implementation<GemsCache>)
+{
+ Context context("When creating Gems cache from '" + stringify(loc) + "':");
+
+ if (! loc.is_regular_file())
+ throw GemsCacheError("Cache '" + stringify(loc) + "' is not a regular file");
+
+ YamlDocument doc(loc);
+
+ TopLevelVisitor v(_imp.operator-> ());
+ doc.top()->accept(&v);
+}
+
+GemsCache::~GemsCache()
+{
+}
+
+GemsCache::Iterator
+GemsCache::begin() const
+{
+ return Iterator(_imp->entries.begin());
+}
+
+GemsCache::Iterator
+GemsCache::end() const
+{
+ return Iterator(_imp->entries.end());
+}
+
diff --git a/0.18.0/paludis/repositories/gems/cache.hh b/0.18.0/paludis/repositories/gems/cache.hh
new file mode 100644
index 000000000..516f279f7
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/cache.hh
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_CACHE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_CACHE_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/collection.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/version_requirements.hh>
+
+#include <libwrapiter/libwrapiter.hh>
+
+namespace paludis
+{
+ class FSEntry;
+
+#include <paludis/repositories/gems/cache-sr.hh>
+
+ class GemsCache :
+ private InstantiationPolicy<GemsCache, instantiation_method::NonCopyableTag>,
+ private PrivateImplementationPattern<GemsCache>
+ {
+ public:
+ GemsCache(const FSEntry &);
+ ~GemsCache();
+
+ typedef libwrapiter::ForwardIterator<GemsCache, const GemsCacheEntry> Iterator;
+ Iterator begin() const;
+ Iterator end() const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/cache.sr b/0.18.0/paludis/repositories/gems/cache.sr
new file mode 100644
index 000000000..cae95a030
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/cache.sr
@@ -0,0 +1,18 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_GemsCacheEntry()
+{
+ key name PackageNamePart
+ key version VersionSpec
+ key summary std::string
+ key description std::string
+ key homepage std::string
+ key required_ruby_version "std::tr1::shared_ptr<VersionRequirements>"
+ key authors "std::tr1::shared_ptr<SequentialCollection<std::string> >"
+ key dependencies "std::tr1::shared_ptr<SequentialCollection<std::string> >"
+ key requirements "std::tr1::shared_ptr<SequentialCollection<std::string> >"
+
+ allow_named_args
+}
+
diff --git a/0.18.0/paludis/repositories/gems/cache_TEST.cc b/0.18.0/paludis/repositories/gems/cache_TEST.cc
new file mode 100644
index 000000000..c842d9455
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/cache_TEST.cc
@@ -0,0 +1,93 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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/cache.hh>
+#include <paludis/repositories/gems/gems_repository_exceptions.hh>
+#include <paludis/repositories/gems/yaml.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/environment/test/test_environment.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct GemsRepositoryCacheEntriesTest : TestCase
+ {
+ GemsRepositoryCacheEntriesTest() : TestCase("cache entries") { }
+
+ void run()
+ {
+ GemsCache cache(FSEntry("cache_TEST_dir/entries"));
+
+ TEST_CHECK_EQUAL(std::distance(cache.begin(), cache.end()), 2);
+
+ GemsCache::Iterator c(cache.begin());
+ TEST_CHECK(c != cache.end());
+
+ TEST_CHECK_EQUAL(c->name, PackageNamePart("foo"));
+ TEST_CHECK_EQUAL(c->homepage, "http://foo.com/");
+ TEST_CHECK_EQUAL(c->version, VersionSpec("1.2.3"));
+
+ TEST_CHECK(c->required_ruby_version);
+ TEST_CHECK_EQUAL(std::distance(c->required_ruby_version->begin(),
+ c->required_ruby_version->end()), 1);
+ TEST_CHECK_EQUAL(c->required_ruby_version->begin()->version_operator, VersionOperator(">"));
+ TEST_CHECK_EQUAL(c->required_ruby_version->begin()->version_spec, VersionSpec("1.8.0"));
+
+ ++c;
+ TEST_CHECK(c != cache.end());
+
+ TEST_CHECK_EQUAL(c->name, PackageNamePart("bar"));
+ TEST_CHECK_EQUAL(c->homepage, "");
+ TEST_CHECK_EQUAL(c->version, VersionSpec("2.3.4"));
+ TEST_CHECK(c->required_ruby_version);
+ TEST_CHECK(c->required_ruby_version->empty());
+
+ ++c;
+ TEST_CHECK(c == cache.end());
+ }
+ } test_cache_entries;
+
+ struct GemsRepositoryCacheNoFileTest : TestCase
+ {
+ GemsRepositoryCacheNoFileTest() : TestCase("cache no file") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(GemsCache(FSEntry("cache_TEST_dir/nofile")), GemsCacheError);
+ }
+ } test_cache_no_file;
+
+ struct GemsRepositoryCacheBrokenTest : TestCase
+ {
+ GemsRepositoryCacheBrokenTest() : TestCase("cache broken file") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(GemsCache(FSEntry("cache_TEST_dir/broken")), YamlError);
+ }
+ } test_cache_broken;
+}
+
+
+
diff --git a/0.18.0/paludis/repositories/gems/cache_TEST_cleanup.sh b/0.18.0/paludis/repositories/gems/cache_TEST_cleanup.sh
new file mode 100755
index 000000000..c75183a0e
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/cache_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d cache_TEST_dir ] ; then
+ rm -fr cache_TEST_dir
+else
+ true
+fi
+
diff --git a/0.18.0/paludis/repositories/gems/cache_TEST_setup.sh b/0.18.0/paludis/repositories/gems/cache_TEST_setup.sh
new file mode 100755
index 000000000..826220cd7
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/cache_TEST_setup.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir cache_TEST_dir || exit 1
+cd cache_TEST_dir || exit 1
+
+cat <<END > entries
+--- !ruby/object:Gem::Cache
+gems:
+ foo-1.2.3: !ruby/object:Gem::Specification
+ name: foo
+ homepage: http://foo.com/
+ version: !ruby/object:Gem::Version
+ version: 1.2.3
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
+ requirements:
+ - - ">"
+ - !ruby/object:Gem::Version
+ version: 1.8.0
+ version:
+
+ bar-2.3.4: !ruby/object:Gem::Specification
+ name: bar
+ version: !ruby/object:Gem::Version
+ version: 2.3.4
+
+END
+
+cat <<"END" > broken
+foo:
+ [ [ foo:
+END
+
diff --git a/0.18.0/paludis/repositories/gems/gems_repository.cc b/0.18.0/paludis/repositories/gems/gems_repository.cc
new file mode 100644
index 000000000..9feeb54aa
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository.cc
@@ -0,0 +1,290 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "gems_repository.hh"
+
+using namespace paludis;
+
+#include <paludis/repositories/gems/gems_repository-sr.cc>
+#include <paludis/repositories/gems/gems_version_metadata.hh>
+#include <paludis/repositories/gems/cache.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/log.hh>
+#include <paludis/syncer.hh>
+#include <paludis/package_database.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/environment.hh>
+
+#include <paludis/portage_dep_parser.hh>
+
+namespace paludis
+{
+ typedef std::map<VersionSpec, GemsRepositoryEntry> Versions;
+ typedef MakeHashedMap<PackageNamePart, Versions>::Type Packages;
+
+ template<>
+ struct Implementation<GemsRepository>
+ {
+ const GemsRepositoryParams params;
+
+ void need_entries() const;
+
+ mutable bool has_entries;
+ mutable Packages packages;
+
+ Implementation(const GemsRepositoryParams & p) :
+ params(p),
+ has_entries(false)
+ {
+ }
+ };
+
+ void
+ Implementation<GemsRepository>::need_entries() const
+ {
+ if (has_entries)
+ return;
+
+ Context context("When loading Gems repository entries:");
+
+ GemsCache cache(params.location / "yaml");
+ for (GemsCache::Iterator g(cache.begin()), g_end(cache.end()) ;
+ g != g_end ; ++g)
+ {
+ std::tr1::shared_ptr<VersionMetadata> m(new GemsVersionMetadata(g->version));
+ m->homepage = g->homepage;
+ if (g->description.empty())
+ m->description = g->summary;
+ else
+ m->description = g->description;
+
+ Packages::iterator v(packages.insert(std::make_pair(g->name, Versions())).first);
+ v->second.insert(std::make_pair(g->version, m));
+ }
+
+ has_entries = true;
+ }
+}
+
+bool
+GemsRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ return stringify(c) == "gems";
+}
+
+bool
+GemsRepository::do_has_package_named(const QualifiedPackageName & c) const
+{
+ if (! do_has_category_named(c.category))
+ return false;
+
+ _imp->need_entries();
+ return _imp->packages.end() != _imp->packages.find(c.package);
+
+ return false;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+GemsRepository::do_category_names() const
+{
+ static std::tr1::shared_ptr<CategoryNamePartCollection> names(new CategoryNamePartCollection::Concrete);
+ if (names->empty())
+ names->insert(CategoryNamePart("gems"));
+
+ return names;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+GemsRepository::do_package_names(const CategoryNamePart & c) const
+{
+ if (! has_category_named(c))
+ return std::tr1::shared_ptr<const QualifiedPackageNameCollection>(new QualifiedPackageNameCollection::Concrete);
+
+ _imp->need_entries();
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ for (Packages::const_iterator i(_imp->packages.begin()), i_end(_imp->packages.end()) ;
+ i != i_end ; ++i)
+ result->insert(c + i->first);
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+GemsRepository::do_version_specs(const QualifiedPackageName & p) const
+{
+ if (! has_category_named(p.category))
+ return std::tr1::shared_ptr<const VersionSpecCollection>(new VersionSpecCollection::Concrete);
+
+ _imp->need_entries();
+
+ std::tr1::shared_ptr<VersionSpecCollection> result(new VersionSpecCollection::Concrete);
+ Packages::const_iterator i(_imp->packages.find(p.package));
+ if (i != _imp->packages.end())
+ std::copy(i->second.begin(), i->second.end(), transform_inserter(
+ result->inserter(), SelectFirst<VersionSpec, GemsRepositoryEntry>()));
+
+ return result;
+}
+
+bool
+GemsRepository::do_has_version(const QualifiedPackageName & q, const VersionSpec &) const
+{
+ if (! has_category_named(q.category))
+ return false;
+
+ _imp->need_entries();
+
+ return false;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+GemsRepository::do_version_metadata(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_category_named(q.category))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ _imp->need_entries();
+
+ Packages::const_iterator i(_imp->packages.find(q.package));
+ if (i == _imp->packages.end())
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ Versions::const_iterator j(i->second.find(v));
+ if (j == i->second.end())
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ return j->second.metadata;
+}
+
+bool
+GemsRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+GemsRepository::do_install(const QualifiedPackageName &, const VersionSpec &, const InstallOptions &) const
+{
+}
+
+std::tr1::shared_ptr<DepAtom>
+GemsRepository::do_package_set(const SetName &) const
+{
+ return std::tr1::shared_ptr<DepAtom>();
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+GemsRepository::sets_list() const
+{
+ return std::tr1::shared_ptr<SetsCollection>(new SetsCollection::Concrete);
+}
+
+bool
+GemsRepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+
+ if (_imp->params.yaml_uri.empty())
+ return false;
+
+ std::string::size_type p;
+ if (std::string::npos == ((p = _imp->params.yaml_uri.find(':'))))
+ throw ConfigurationError("Don't recognise URI '" + _imp->params.yaml_uri + "'");
+
+ std::string protocol(_imp->params.yaml_uri.substr(0, p));
+
+ std::list<std::string> fetchers_dirs;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->params.environment->fetchers_dirs(),
+ std::back_inserter(fetchers_dirs));
+
+ Log::get_instance()->message(ll_debug, lc_context, "looking for syncer protocol '"
+ + stringify(protocol) + "'");
+
+ FSEntry fetcher("/var/empty");
+ bool ok(false);
+ for (std::list<std::string>::const_iterator d(fetchers_dirs.begin()),
+ d_end(fetchers_dirs.end()) ; d != d_end && ! ok; ++d)
+ {
+ fetcher = FSEntry(*d) / ("do" + protocol);
+ if (fetcher.exists() && fetcher.has_permission(fs_ug_owner, fs_perm_execute))
+ ok = true;
+
+ Log::get_instance()->message(ll_debug, lc_no_context, "Trying '" + stringify(fetcher) + "': "
+ + (ok ? "ok" : "not ok"));
+ }
+
+ if (! ok)
+ throw ConfigurationError("Don't know how to fetch URI '" + _imp->params.yaml_uri + "'");
+
+ (_imp->params.location / "yaml").unlink();
+ if (run_command(stringify(fetcher) + " '" +_imp->params.yaml_uri + "' '" +
+ stringify(_imp->params.location / "yaml") + "'"))
+ throw SyncFailedError(stringify(_imp->params.location / "yaml"), _imp->params.yaml_uri);
+
+ return true;
+}
+
+GemsRepository::GemsRepository(const GemsRepositoryParams & p) :
+ Repository(RepositoryName("gems"),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .contents_interface(0)
+ .installable_interface(this)
+ .installed_interface(0)
+ .news_interface(0)
+ .sets_interface(this)
+ .syncable_interface(this)
+ .uninstallable_interface(0)
+ .use_interface(0)
+ .world_interface(0)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .virtuals_interface(0)
+ .provides_interface(0)
+ .config_interface(0)
+ .destination_interface(0),
+ "gems"),
+ PrivateImplementationPattern<GemsRepository>(new Implementation<GemsRepository>(p))
+{
+}
+
+GemsRepository::~GemsRepository()
+{
+}
+
+void
+GemsRepository::invalidate()
+{
+ _imp.reset(new Implementation<GemsRepository>(_imp->params));
+}
+
+void
+GemsRepository::regenerate_cache() const
+{
+}
+
+std::tr1::shared_ptr<const RepositoryInfo>
+GemsRepository::info(bool) const
+{
+ return std::tr1::shared_ptr<RepositoryInfo>(new RepositoryInfo);
+}
+
diff --git a/0.18.0/paludis/repositories/gems/gems_repository.hh b/0.18.0/paludis/repositories/gems/gems_repository.hh
new file mode 100644
index 000000000..7927b607c
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository.hh
@@ -0,0 +1,65 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#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/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <string>
+
+namespace paludis
+{
+ class PackageDatabase;
+
+#include <paludis/repositories/gems/gems_repository-sr.hh>
+
+ class PALUDIS_VISIBLE GemsRepository :
+ public Repository,
+ public RepositoryInstallableInterface,
+ public RepositorySyncableInterface,
+ public RepositorySetsInterface,
+ private PrivateImplementationPattern<GemsRepository>
+ {
+ protected:
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual std::tr1::shared_ptr<DepAtom> do_package_set(const SetName &) const;
+
+ virtual std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+
+ virtual bool do_sync() const;
+
+ public:
+ virtual std::tr1::shared_ptr<const RepositoryInfo> info(bool verbose) const;
+
+ GemsRepository(const GemsRepositoryParams &);
+ ~GemsRepository();
+
+ virtual void invalidate();
+ virtual void regenerate_cache() const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/gems_repository.sr b/0.18.0/paludis/repositories/gems/gems_repository.sr
new file mode 100644
index 000000000..416170f38
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository.sr
@@ -0,0 +1,20 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_GemsRepositoryParams()
+{
+ key environment "const Environment *"
+ key location FSEntry
+ key distdir FSEntry
+ key yaml_uri std::string
+ key root FSEntry
+ key buildroot FSEntry
+
+ allow_named_args
+}
+
+make_class_GemsRepositoryEntry()
+{
+ key metadata "std::tr1::shared_ptr<VersionMetadata>"
+}
+
diff --git a/0.18.0/paludis/repositories/gems/gems_repository_TEST.cc b/0.18.0/paludis/repositories/gems/gems_repository_TEST.cc
new file mode 100644
index 000000000..ca850c7a8
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository_TEST.cc
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/make_gems_repository.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/environment/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct GemsRepositoryRepoNameTest : TestCase
+ {
+ GemsRepositoryRepoNameTest() : TestCase("repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "gems");
+ keys->insert("location", "gems_repository_TEST_dir/repo1");
+ std::tr1::shared_ptr<Repository> repo(make_gems_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "gems");
+ }
+ } test_portage_repository_repo_name;
+}
+
+
diff --git a/0.18.0/paludis/repositories/gems/gems_repository_TEST_cleanup.sh b/0.18.0/paludis/repositories/gems/gems_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..5d20e5c2b
--- /dev/null
+++ b/0.18.0/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/0.18.0/paludis/repositories/gems/gems_repository_TEST_setup.sh b/0.18.0/paludis/repositories/gems/gems_repository_TEST_setup.sh
new file mode 100755
index 000000000..ada6cd804
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository_TEST_setup.sh
@@ -0,0 +1,5 @@
+#!/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/0.18.0/paludis/repositories/gems/gems_repository_exceptions.cc b/0.18.0/paludis/repositories/gems/gems_repository_exceptions.cc
new file mode 100644
index 000000000..cc7905b1b
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository_exceptions.cc
@@ -0,0 +1,35 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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 "gems_repository_exceptions.hh"
+
+using namespace paludis;
+
+GemsRepositoryConfigurationError::GemsRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("Gems repository configuration error: " + msg)
+{
+}
+
+GemsCacheError::GemsCacheError(
+ const std::string & msg) throw () :
+ ConfigurationError("Gems repository cache error: " + msg)
+{
+}
+
diff --git a/0.18.0/paludis/repositories/gems/gems_repository_exceptions.hh b/0.18.0/paludis/repositories/gems/gems_repository_exceptions.hh
new file mode 100644
index 000000000..38a0ca94f
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_repository_exceptions.hh
@@ -0,0 +1,46 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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_EXCEPTIONS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_GEMS_REPOSITORY_EXCEPTIONS_HH 1
+
+#include <paludis/util/exception.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE GemsRepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ GemsRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+
+ class PALUDIS_VISIBLE GemsCacheError :
+ public ConfigurationError
+ {
+ public:
+ GemsCacheError(const std::string & msg) throw ();
+ };
+
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/gems_version_metadata.cc b/0.18.0/paludis/repositories/gems/gems_version_metadata.cc
new file mode 100644
index 000000000..96e40813c
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_version_metadata.cc
@@ -0,0 +1,43 @@
+/* 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 "gems_version_metadata.hh"
+#include <paludis/portage_dep_parser.hh>
+
+using namespace paludis;
+
+GemsVersionMetadata::GemsVersionMetadata(const VersionSpec & v) :
+ VersionMetadata(
+ VersionMetadataBase(SlotName(stringify(v)), "", "", "paludis-1"),
+ VersionMetadataCapabilities::create()
+ .deps_interface(this)
+ .ebuild_interface(0)
+ .cran_interface(0)
+ .virtual_interface(0)
+ .origins_interface(0)
+ .license_interface(0)
+ ),
+ VersionMetadataDepsInterface(&PortageDepParser::parse_depend)
+{
+}
+
+GemsVersionMetadata::~GemsVersionMetadata()
+{
+}
+
diff --git a/0.18.0/paludis/repositories/gems/gems_version_metadata.hh b/0.18.0/paludis/repositories/gems/gems_version_metadata.hh
new file mode 100644
index 000000000..cd141b81a
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/gems_version_metadata.hh
@@ -0,0 +1,44 @@
+/* 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_VERSION_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_GEMS_VERSION_METADATA_HH 1
+
+#include <paludis/version_metadata.hh>
+#include <paludis/version_spec.hh>
+
+namespace paludis
+{
+ /**
+ * Version metadata for a Gems repository entry.
+ *
+ * \see GemsRepository
+ * \ingroup grpgemsrepository
+ */
+ class GemsVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataDepsInterface
+ {
+ public:
+ GemsVersionMetadata(const VersionSpec &);
+ virtual ~GemsVersionMetadata();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/make_gems_repository.cc b/0.18.0/paludis/repositories/gems/make_gems_repository.cc
new file mode 100644
index 000000000..c9fd554ac
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/make_gems_repository.cc
@@ -0,0 +1,64 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "make_gems_repository.hh"
+#include <paludis/repositories/gems/gems_repository_exceptions.hh>
+
+using namespace paludis;
+
+std::tr1::shared_ptr<Repository>
+paludis::make_gems_repository(Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
+ m->find("repo_file")->second);
+
+ Context context("When making gems repository from repo_file '" + repo_file + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw GemsRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string distdir;
+ if (m->end() == m->find("distdir") || ((distdir = m->find("distdir")->second)).empty())
+ distdir = location + "/distfiles";
+
+ std::string yaml_uri;
+ if (m->end() != m->find("yaml_uri"))
+ yaml_uri = m->find("yaml_uri")->second;
+
+ std::string root;
+ if (m->end() == m->find("root") || ((root = m->find("root")->second)).empty())
+ root = "/";
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = "/var/tmp/paludis";
+
+ return std::tr1::shared_ptr<Repository>(new GemsRepository(GemsRepositoryParams::create()
+ .environment(env)
+ .location(location)
+ .distdir(distdir)
+ .yaml_uri(yaml_uri)
+ .root(root)
+ .buildroot(buildroot)));
+
+}
+
+
diff --git a/0.18.0/paludis/repositories/gems/make_gems_repository.hh b/0.18.0/paludis/repositories/gems/make_gems_repository.hh
new file mode 100644
index 000000000..154e4465f
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/make_gems_repository.hh
@@ -0,0 +1,32 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_MAKE_GEMS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMS_MAKE_GEMS_REPOSITORY_HH 1
+
+#include <paludis/repositories/gems/gems_repository.hh>
+
+namespace paludis
+{
+ std::tr1::shared_ptr<Repository>
+ make_gems_repository(Environment * const,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >) PALUDIS_VISIBLE;
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/registration.cc b/0.18.0/paludis/repositories/gems/registration.cc
new file mode 100644
index 000000000..8fc967b03
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/registration.cc
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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/make_gems_repository.hh>
+#include "config.h"
+
+using namespace paludis;
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("gems", &make_gems_repository);
+}
+
+#endif
+
+
diff --git a/0.18.0/paludis/repositories/gems/yaml.cc b/0.18.0/paludis/repositories/gems/yaml.cc
new file mode 100644
index 000000000..0a09e50ff
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/yaml.cc
@@ -0,0 +1,368 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/fs_entry.hh>
+#include <paludis/util/stringify.hh>
+#include <yaml.h>
+#include <list>
+
+using namespace paludis;
+
+YamlNode::YamlNode()
+{
+}
+
+YamlNode::~YamlNode()
+{
+}
+
+YamlScalarNode::YamlScalarNode(const std::string & v, const std::string & t) :
+ _value(v),
+ _tag(t)
+{
+}
+
+namespace paludis
+{
+ template<>
+ struct Implementation<YamlMappingNode>
+ {
+ std::list<std::pair<std::tr1::shared_ptr<YamlScalarNode>, std::tr1::shared_ptr<YamlNode> > > nodes;
+ };
+
+ template<>
+ struct Implementation<YamlSequenceNode>
+ {
+ std::list<std::tr1::shared_ptr<YamlNode> > nodes;
+ };
+}
+
+
+YamlMappingNode::YamlMappingNode() :
+ PrivateImplementationPattern<YamlMappingNode>(new Implementation<YamlMappingNode>)
+{
+}
+
+YamlMappingNode::Iterator
+YamlMappingNode::begin() const
+{
+ return Iterator(_imp->nodes.begin());
+}
+
+YamlMappingNode::Iterator
+YamlMappingNode::end() const
+{
+ return Iterator(_imp->nodes.end());
+}
+
+std::pair<std::tr1::shared_ptr<YamlScalarNode>, std::tr1::shared_ptr<YamlNode> > &
+YamlMappingNode::back()
+{
+ return _imp->nodes.back();
+}
+
+YamlSequenceNode::YamlSequenceNode() :
+ PrivateImplementationPattern<YamlSequenceNode>(new Implementation<YamlSequenceNode>)
+{
+}
+
+YamlSequenceNode::Iterator
+YamlSequenceNode::begin() const
+{
+ return Iterator(_imp->nodes.begin());
+}
+
+YamlSequenceNode::Iterator
+YamlSequenceNode::end() const
+{
+ return Iterator(_imp->nodes.end());
+}
+
+void
+YamlSequenceNode::add(std::tr1::shared_ptr<YamlNode> node)
+{
+ _imp->nodes.push_back(node);
+}
+
+void
+YamlMappingNode::add(std::tr1::shared_ptr<YamlScalarNode> a, std::tr1::shared_ptr<YamlNode> b)
+{
+ _imp->nodes.push_back(std::make_pair(a, b));
+}
+
+namespace paludis
+{
+ template<>
+ struct Implementation<YamlDocument>
+ {
+ std::tr1::shared_ptr<YamlSequenceNode> top;
+
+ void parse(yaml_parser_t * parser);
+ std::tr1::shared_ptr<YamlScalarNode> parse_scalar(yaml_parser_t * parser);
+
+ Implementation() :
+ top(new YamlSequenceNode)
+ {
+ }
+ };
+}
+
+namespace
+{
+ template <typename PtrType_, typename ReturnType_ = void>
+ class PtrHolder
+ {
+ private:
+ PtrType_ _ptr;
+ ReturnType_ (* _free_func) (PtrType_);
+ bool _new_used;
+
+ PtrHolder(const PtrHolder &);
+ void operator= (const PtrHolder &);
+
+ public:
+ PtrHolder(PtrType_ ptr, ReturnType_ (* free_func) (PtrType_), bool new_used = false) :
+ _ptr(ptr),
+ _free_func(free_func),
+ _new_used(new_used)
+ {
+ }
+
+ ~PtrHolder()
+ {
+ if (0 != _ptr)
+ {
+ _free_func(_ptr);
+ if (_new_used)
+ delete _ptr;
+ }
+ }
+
+ operator PtrType_ () const
+ {
+ return _ptr;
+ }
+ };
+
+ struct ScalarAdder :
+ YamlNodeVisitorTypes::Visitor
+ {
+ std::tr1::shared_ptr<YamlScalarNode> a;
+
+ ScalarAdder(std::tr1::shared_ptr<YamlScalarNode> aa) :
+ a(aa)
+ {
+ }
+
+ void visit(YamlMappingNode * n)
+ {
+ if (n->empty() || n->back().second)
+ n->add(a, std::tr1::shared_ptr<YamlNode>());
+ else
+ n->back().second = a;
+ }
+
+ void visit(YamlScalarNode *) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw YamlError("Can't add a YamlScalarNode to a YamlScalarNode");
+ }
+
+ void visit(YamlSequenceNode * n)
+ {
+ n->add(a);
+ }
+ };
+
+ struct NonScalarAdder :
+ YamlNodeVisitorTypes::Visitor
+ {
+ std::tr1::shared_ptr<YamlNode> a;
+
+ NonScalarAdder(std::tr1::shared_ptr<YamlNode> aa) :
+ a(aa)
+ {
+ }
+
+ void visit(YamlMappingNode * n)
+ {
+ if (n->empty() || n->back().second)
+ throw YamlError("Can't add a non YamlScalarNode to a YamlMappingNode on the left");
+ else
+ n->back().second = a;
+ }
+
+ void visit(YamlScalarNode *) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw YamlError("Can't add a YamlScalarNode to a YamlScalarNode");
+ }
+
+ void visit(YamlSequenceNode * n)
+ {
+ n->add(a);
+ }
+ };
+}
+
+YamlDocument::YamlDocument(const std::string & s) :
+ PrivateImplementationPattern<YamlDocument>(new Implementation<YamlDocument>)
+{
+ Context context("When creating YamlDocument from string:");
+
+ PtrHolder<yaml_parser_t *> parser(new yaml_parser_t, yaml_parser_delete, true);
+ yaml_parser_initialize(parser);
+ /* silly c api */
+ yaml_parser_set_input_string(parser, const_cast<unsigned char *>(
+ reinterpret_cast<const unsigned char *>(s.c_str())), s.length());
+
+ _imp->parse(parser);
+}
+
+YamlDocument::YamlDocument(const FSEntry & loc) :
+ PrivateImplementationPattern<YamlDocument>(new Implementation<YamlDocument>)
+{
+ Context context("When creating YamlDocument from location '" + stringify(loc) + "':");
+
+ if (! loc.is_regular_file())
+ throw YamlError("Document '" + stringify(loc) + "' is not a regular file");
+
+ PtrHolder<FILE *, int> f(std::fopen(stringify(loc).c_str(), "rb"), &std::fclose);
+ if (! f)
+ throw YamlError("Document '" + stringify(loc) + "' is not readable");
+
+ PtrHolder<yaml_parser_t *> parser(new yaml_parser_t, yaml_parser_delete, true);
+ yaml_parser_initialize(parser);
+ yaml_parser_set_input_file(parser, f);
+
+ _imp->parse(parser);
+}
+
+void
+Implementation<YamlDocument>::parse(yaml_parser_t * parser)
+{
+ std::list<std::tr1::shared_ptr<YamlNode> > stack;
+ stack.push_back(top);
+
+ bool done(false);
+
+ while (! done)
+ {
+ PtrHolder<yaml_event_t *> event_holder(new yaml_event_t, yaml_event_delete, true);
+ std::memset(event_holder, 0, sizeof(*event_holder));
+ if (! yaml_parser_parse(parser, event_holder))
+ throw YamlError("Error parsing document");
+
+ yaml_event_t * event(event_holder);
+
+ switch (event->type)
+ {
+ case YAML_STREAM_START_EVENT:
+ break;
+
+ case YAML_STREAM_END_EVENT:
+ done = true;
+ break;
+
+ case YAML_MAPPING_START_EVENT:
+ {
+ std::tr1::shared_ptr<YamlMappingNode> node(new YamlMappingNode);
+ if (stack.empty())
+ throw YamlError("Error building tree: stack empty on YAML_SEQUENCE_START_EVENT");
+
+ if (stack.back())
+ {
+ NonScalarAdder a(node);
+ stack.back()->accept(&a);
+ }
+ else
+ stack.back() = node;
+ stack.push_back(node);
+ }
+ break;
+
+ case YAML_MAPPING_END_EVENT:
+ case YAML_SEQUENCE_END_EVENT:
+ if (stack.empty())
+ throw YamlError("Error building tree: stack empty on YAML_*_END_EVENT");
+ stack.pop_back();
+ break;
+
+ case YAML_SEQUENCE_START_EVENT:
+ {
+ std::tr1::shared_ptr<YamlSequenceNode> node(new YamlSequenceNode);
+ if (stack.empty())
+ throw YamlError("Error building tree: stack empty on YAML_SEQUENCE_START_EVENT");
+ if (stack.back())
+ {
+ NonScalarAdder a(node);
+ stack.back()->accept(&a);
+ }
+ else
+ stack.back() = node;
+ stack.push_back(node);
+ }
+ break;
+
+ case YAML_SCALAR_EVENT:
+ {
+ if (stack.empty())
+ throw YamlError("Error building tree: stack empty on YAML_SCALAR_EVENT");
+ std::tr1::shared_ptr<YamlScalarNode> node(new YamlScalarNode(
+ event->data.scalar.value ? reinterpret_cast<const char *>(event->data.scalar.value) : "",
+ event->data.scalar.tag ? reinterpret_cast<const char *>(event->data.scalar.tag) : ""));
+ if (stack.back())
+ {
+ ScalarAdder a(node);
+ stack.back()->accept(&a);
+ }
+ else
+ stack.back() = node;
+ }
+ break;
+
+ case YAML_NO_EVENT:
+ case YAML_DOCUMENT_START_EVENT:
+ case YAML_DOCUMENT_END_EVENT:
+ case YAML_ALIAS_EVENT:
+ break;
+ }
+ };
+
+ if (stack.empty())
+ throw YamlError("Error building tree: stack empty at end");
+ stack.pop_back();
+ if (! stack.empty())
+ throw YamlError("Error building tree: stack not empty at end");
+}
+
+YamlDocument::~YamlDocument()
+{
+}
+
+std::tr1::shared_ptr<const YamlNode>
+YamlDocument::top() const
+{
+ return _imp->top;
+}
+
+YamlError::YamlError(const std::string & msg) throw () :
+ ConfigurationError(msg)
+{
+}
+
diff --git a/0.18.0/paludis/repositories/gems/yaml.hh b/0.18.0/paludis/repositories/gems/yaml.hh
new file mode 100644
index 000000000..31084fb2e
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/yaml.hh
@@ -0,0 +1,130 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/util/visitor.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ class FSEntry;
+
+ class YamlNode;
+ class YamlScalarNode;
+ class YamlSequenceNode;
+ class YamlMappingNode;
+
+ typedef VisitorTypes<YamlScalarNode *, YamlSequenceNode *, YamlMappingNode *> YamlNodeVisitorTypes;
+
+ class YamlError :
+ public ConfigurationError
+ {
+ public:
+ YamlError(const std::string & msg) throw ();
+ };
+
+ class YamlNode :
+ public virtual VisitableInterface<YamlNodeVisitorTypes>,
+ private InstantiationPolicy<YamlNode, instantiation_method::NonCopyableTag>
+ {
+ protected:
+ YamlNode();
+
+ public:
+ virtual ~YamlNode();
+ };
+
+ class YamlScalarNode :
+ public YamlNode,
+ public Visitable<YamlScalarNode, YamlNodeVisitorTypes>
+ {
+ private:
+ std::string _value;
+ std::string _tag;
+
+ public:
+ YamlScalarNode(const std::string &, const std::string &);
+
+ std::string value() const
+ {
+ return _value;
+ }
+
+ std::string tag() const
+ {
+ return _tag;
+ }
+ };
+
+ class YamlMappingNode :
+ public YamlNode,
+ public Visitable<YamlMappingNode, YamlNodeVisitorTypes>,
+ private PrivateImplementationPattern<YamlMappingNode>
+ {
+ public:
+ YamlMappingNode();
+
+ void add(std::tr1::shared_ptr<YamlScalarNode>, std::tr1::shared_ptr<YamlNode>);
+
+ typedef libwrapiter::ForwardIterator<YamlMappingNode,
+ const std::pair<std::tr1::shared_ptr<YamlScalarNode>, std::tr1::shared_ptr<YamlNode> > > Iterator;
+ Iterator begin() const;
+ Iterator end() const;
+
+ std::pair<std::tr1::shared_ptr<YamlScalarNode>, std::tr1::shared_ptr<YamlNode> > & back();
+
+ bool empty() const
+ {
+ return begin() == end();
+ }
+ };
+
+ class YamlSequenceNode :
+ public YamlNode,
+ public Visitable<YamlSequenceNode, YamlNodeVisitorTypes>,
+ private PrivateImplementationPattern<YamlSequenceNode>
+ {
+ public:
+ YamlSequenceNode();
+
+ typedef libwrapiter::ForwardIterator<YamlSequenceNode, const std::tr1::shared_ptr<YamlNode> > Iterator;
+ Iterator begin() const;
+ Iterator end() const;
+
+ void add(std::tr1::shared_ptr<YamlNode>);
+ };
+
+ class YamlDocument :
+ private PrivateImplementationPattern<YamlDocument>,
+ private InstantiationPolicy<YamlDocument, instantiation_method::NonCopyableTag>
+ {
+ public:
+ YamlDocument(const std::string &);
+ YamlDocument(const FSEntry &);
+ ~YamlDocument();
+
+ std::tr1::shared_ptr<const YamlNode> top() const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/gems/yaml_TEST.cc b/0.18.0/paludis/repositories/gems/yaml_TEST.cc
new file mode 100644
index 000000000..0d463f8ae
--- /dev/null
+++ b/0.18.0/paludis/repositories/gems/yaml_TEST.cc
@@ -0,0 +1,145 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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/yaml.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace
+{
+ struct Dumper :
+ YamlNodeVisitorTypes::ConstVisitor
+ {
+ std::string str;
+
+ void visit(const YamlSequenceNode * n)
+ {
+ str.append("seq<");
+ std::for_each(n->begin(), n->end(), accept_visitor(this));
+ str.append(">");
+ }
+
+ void visit(const YamlScalarNode * n)
+ {
+ str.append("scalar<");
+ str.append(n->value());
+ str.append(">");
+ }
+
+ void visit(const YamlMappingNode * n)
+ {
+ str.append("map<");
+ bool need_comma(false);
+ for (YamlMappingNode::Iterator i(n->begin()), i_end(n->end()) ; i != i_end ; ++i)
+ {
+ if (need_comma)
+ str.append(",");
+
+ i->first->accept(this);
+ str.append("=");
+ i->second->accept(this);
+ need_comma = true;
+ }
+ str.append(">");
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct YamlTest : TestCase
+ {
+ YamlTest() : TestCase("yaml") { }
+
+ void run()
+ {
+ YamlDocument yaml("foo");
+ Dumper d;
+ yaml.top()->accept(&d);
+ TEST_CHECK_EQUAL(d.str, "seq<scalar<foo>>");
+ }
+ } test_yaml;
+
+ struct YamlSequenceTest : TestCase
+ {
+ YamlSequenceTest() : TestCase("yaml sequence") { }
+
+ void run()
+ {
+ YamlDocument yaml(
+ "- a\n"
+ "- b\n"
+ "- c\n");
+ Dumper d;
+ yaml.top()->accept(&d);
+ TEST_CHECK_EQUAL(d.str, "seq<seq<scalar<a>scalar<b>scalar<c>>>");
+ }
+ } test_yaml_sequence;
+
+ struct YamlMappingTest : TestCase
+ {
+ YamlMappingTest() : TestCase("yaml mapping") { }
+
+ void run()
+ {
+ YamlDocument yaml(
+ "a: b\n"
+ "c: d\n");
+ Dumper d;
+ yaml.top()->accept(&d);
+ TEST_CHECK_EQUAL(d.str, "seq<map<scalar<a>=scalar<b>,scalar<c>=scalar<d>>>");
+ }
+ } test_yaml_map;
+
+ struct YamlMixedTest : TestCase
+ {
+ YamlMixedTest() : TestCase("yaml mixed") { }
+
+ void run()
+ {
+ YamlDocument yaml(
+"a:\n"
+" b: !c\n"
+" d: e\n"
+" f:\n"
+" - g\n"
+" - h\n"
+"i: j\n");
+ Dumper d;
+ yaml.top()->accept(&d);
+ TEST_CHECK_EQUAL(d.str, "seq<map<scalar<a>=map<scalar<b>=map<scalar<d>=scalar<e>,"
+ "scalar<f>=seq<scalar<g>scalar<h>>>>,scalar<i>=scalar<j>>>");
+ }
+ } test_yaml_mixed;
+
+ struct YamlBadTest : TestCase
+ {
+ YamlBadTest() : TestCase("yaml bad") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(YamlDocument yaml("[ [ foo:\n"), YamlError);
+ }
+ } test_yaml_bad;
+
+}
+
diff --git a/0.18.0/paludis/repositories/nothing/Makefile.am b/0.18.0/paludis/repositories/nothing/Makefile.am
new file mode 100644
index 000000000..6dd9b24a3
--- /dev/null
+++ b/0.18.0/paludis/repositories/nothing/Makefile.am
@@ -0,0 +1,61 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = nothing_repository-sr.hh nothing_repository-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludisnothingrepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisnothingrepository.la
+
+endif
+
+libpaludisnothingrepository_la_SOURCES = \
+ nothing_repository.cc \
+ nothing_repository.hh \
+ registration.cc
+
+libpaludisnothingrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+paludis_repositories_nothing_includedir = $(includedir)/paludis/repositories/nothing/
+
+if ! MONOLITHIC
+
+libpaludisnothingrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+paludis_repositories_nothing_include_HEADERS = \
+ nothing_repository.hh \
+ nothing_repository-sr.hh
+
+EXTRA_DIST = \
+ nothing_repository-sr.hh \
+ nothing_repository-sr.cc \
+ nothing_repository.sr
+
+BUILT_SOURCES = \
+ nothing_repository-sr.hh \
+ nothing_repository-sr.cc
+
+nothing_repository-sr.hh : nothing_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/nothing_repository.sr > $@
+
+nothing_repository-sr.cc : nothing_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/nothing_repository.sr > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/0.18.0/paludis/repositories/nothing/nothing_repository.cc b/0.18.0/paludis/repositories/nothing/nothing_repository.cc
new file mode 100644
index 000000000..13db40879
--- /dev/null
+++ b/0.18.0/paludis/repositories/nothing/nothing_repository.cc
@@ -0,0 +1,258 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "config.h"
+
+#include <paludis/repositories/nothing/nothing_repository.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/syncer.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+
+/** \file
+ * Implementation of NothingRepository.
+ *
+ * \ingroup grpnothingrepository
+ */
+
+using namespace paludis;
+
+#include <paludis/repositories/nothing/nothing_repository-sr.cc>
+
+namespace paludis
+{
+ /**
+ * Implementation data for a NothingRepository.
+ *
+ * \ingroup grpnothingrepository
+ */
+ template <>
+ struct Implementation<NothingRepository>
+ {
+ /// Our name
+ std::string name;
+
+ /// Our location
+ FSEntry location;
+
+ /// Sync URL
+ std::string sync;
+
+ /// Sync options
+ std::string sync_options;
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Environment (for syncing)
+ const Environment * environment;
+
+ /// Constructor.
+ Implementation(const NothingRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+ };
+
+ Implementation<NothingRepository>::Implementation(const NothingRepositoryParams & p) :
+ name(p.name),
+ location(p.location),
+ sync(p.sync),
+ sync_options(p.sync_options),
+ environment(p.environment)
+ {
+ }
+
+ Implementation<NothingRepository>::~Implementation()
+ {
+ }
+}
+
+NothingRepository::NothingRepository(const NothingRepositoryParams & p) try :
+ Repository(RepositoryName(p.name),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(0)
+ .installed_interface(0)
+ .contents_interface(0)
+ .news_interface(0)
+ .sets_interface(0)
+ .syncable_interface(this)
+ .uninstallable_interface(0)
+ .use_interface(0)
+ .world_interface(0)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .virtuals_interface(0)
+ .provides_interface(0)
+ .config_interface(0)
+ .destination_interface(0),
+ "nothing"),
+ PrivateImplementationPattern<NothingRepository>(new Implementation<NothingRepository>(p))
+{
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+ config_info->add_kv("sync", _imp->sync);
+ config_info->add_kv("sync_options", _imp->sync_options);
+ config_info->add_kv("location", stringify(_imp->location));
+
+ _info->add_section(config_info);
+}
+catch (const NameError & e)
+{
+ Context context("When making Nothing repository '" + p.name + "':");
+ throw NothingRepositoryConfigurationError("Caught NameError: " + e.message());
+}
+
+NothingRepository::~NothingRepository()
+{
+}
+
+bool
+NothingRepository::do_has_category_named(const CategoryNamePart &) const
+{
+ return false;
+}
+
+bool
+NothingRepository::do_has_package_named(const QualifiedPackageName &) const
+{
+ return false;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+NothingRepository::do_category_names() const
+{
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+NothingRepository::do_package_names(const CategoryNamePart &) const
+{
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+NothingRepository::do_version_specs(const QualifiedPackageName &) const
+{
+ return std::tr1::shared_ptr<VersionSpecCollection>(new VersionSpecCollection::Concrete);
+}
+
+bool
+NothingRepository::do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+NothingRepository::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+}
+
+std::tr1::shared_ptr<Repository>
+NothingRepository::make_nothing_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
+ m->find("repo_file")->second);
+
+ Context context("When making Nothing repository from repo_file '" + repo_file + "':");
+
+ Log::get_instance()->message(ll_warning, lc_context, "Format 'nothing' is "
+ "deprecated, use 'ebuild' or hook scripts instead");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw NothingRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string sync;
+ if (m->end() != m->find("sync"))
+ sync = m->find("sync")->second;
+
+ std::string name;
+ if (m->end() == m->find("name") || ((name = m->find("name")->second)).empty())
+ throw NothingRepositoryConfigurationError("Key 'name' not specified or empty in '"
+ + repo_file + "'");
+
+ std::string sync_options;
+ if (m->end() != m->find("sync_options"))
+ sync_options = m->find("sync_options")->second;
+
+ if (m->end() != m->find("sync_exclude"))
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The sync_exclude key in '"
+ + repo_file + "' is deprecated in favour of sync_options = --exclude-from=");
+ if (! sync_options.empty())
+ sync_options += " ";
+ sync_options += "--exclude-from='" + m->find("sync_exclude")->second + "'";
+ }
+
+ return std::tr1::shared_ptr<Repository>(new NothingRepository(NothingRepositoryParams::create()
+ .name(name)
+ .location(location)
+ .sync(sync)
+ .sync_options(sync_options)
+ .environment(env)));
+}
+
+NothingRepositoryConfigurationError::NothingRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("Nothing repository configuration error: " + msg)
+{
+}
+
+bool
+NothingRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+bool
+NothingRepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+
+ if (_imp->sync.empty())
+ return false;
+
+ DefaultSyncer syncer(SyncerParams::create()
+ .environment(_imp->environment)
+ .local(stringify(_imp->location))
+ .remote(_imp->sync));
+ SyncOptions opts(_imp->sync_options);
+ syncer.sync(opts);
+
+ return true;
+}
+
+void
+NothingRepository::invalidate()
+{
+}
+
diff --git a/0.18.0/paludis/repositories/nothing/nothing_repository.hh b/0.18.0/paludis/repositories/nothing/nothing_repository.hh
new file mode 100644
index 000000000..970227bb0
--- /dev/null
+++ b/0.18.0/paludis/repositories/nothing/nothing_repository.hh
@@ -0,0 +1,112 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_NOTHING_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_NOTHING_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry.hh>
+
+/** \file
+ * Declarations for the NothingRepository class.
+ *
+ * \ingroup grpnothingrepository
+ */
+
+namespace paludis
+{
+ class PackageDatabase;
+
+#include <paludis/repositories/nothing/nothing_repository-sr.hh>
+
+ /**
+ * A NothingRepository is a Repository that has no content, but can be
+ * synced along with other repositories.
+ *
+ * \ingroup grpnothingrepository
+ */
+ class PALUDIS_VISIBLE NothingRepository :
+ public Repository,
+ public RepositorySyncableInterface,
+ private PrivateImplementationPattern<NothingRepository>
+ {
+ protected:
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual bool do_sync() const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ NothingRepository(const NothingRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static std::tr1::shared_ptr<Repository> make_nothing_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >);
+
+ /**
+ * Destructor.
+ */
+ ~NothingRepository();
+
+ virtual void invalidate();
+ };
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * NothingRepository::make_nothing_repository.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpnothingrepository
+ */
+ class NothingRepositoryConfigurationError : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ NothingRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+}
+
+
+#endif
diff --git a/0.18.0/paludis/repositories/nothing/nothing_repository.sr b/0.18.0/paludis/repositories/nothing/nothing_repository.sr
new file mode 100644
index 000000000..c8d1e2d87
--- /dev/null
+++ b/0.18.0/paludis/repositories/nothing/nothing_repository.sr
@@ -0,0 +1,25 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_NothingRepositoryParams()
+{
+ key location FSEntry
+ key name std::string
+ key sync std::string
+ key sync_options std::string
+
+ key environment "const Environment *"
+
+ allow_named_args
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for a NothingRepository.
+ *
+ * \see NothingRepository
+ * \ingroup grpnothingrepository
+ */
+END
+}
+
+
diff --git a/0.18.0/paludis/repositories/nothing/registration.cc b/0.18.0/paludis/repositories/nothing/registration.cc
new file mode 100644
index 000000000..a675504a6
--- /dev/null
+++ b/0.18.0/paludis/repositories/nothing/registration.cc
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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/nothing/nothing_repository.hh>
+#include "config.h"
+
+using namespace paludis;
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("nothing", &NothingRepository::make_nothing_repository);
+}
+
+#endif
+
+
diff --git a/0.18.0/paludis/repositories/portage/Makefile.am b/0.18.0/paludis/repositories/portage/Makefile.am
new file mode 100644
index 000000000..225039cc3
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/Makefile.am
@@ -0,0 +1,239 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = \
+ portage_repository-sr.hh portage_repository-sr.cc \
+ glsa-sr.hh glsa-sr.cc \
+ portage_repository_params-sr.hh portage_repository_params-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+if ENABLE_GLSA
+
+noinst_LTLIBRARIES = \
+ libpaludisportagerepository.la \
+ libpaludisportagerepositoryxmlthings.la
+
+else
+
+noinst_LTLIBRARIES = \
+ libpaludisportagerepository.la
+
+endif
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisportagerepository.la
+
+if ENABLE_GLSA
+
+lib_LTLIBRARIES = libpaludisportagerepositoryxmlthings.la
+
+endif
+
+endif
+
+paludis_repositories_portage_includedir = $(includedir)/paludis/repositories/portage/
+libpaludisportagerepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_portage_include_HEADERS = \
+ glsa.hh \
+ glsa-sr.hh \
+ portage_repository-sr.hh \
+ portage_repository.hh \
+ portage_repository_profile_file.hh \
+ portage_repository_profile.hh \
+ portage_repository_exceptions.hh \
+ portage_repository_news.hh \
+ portage_repository_params.hh \
+ portage_repository_params-sr.hh \
+ portage_repository_sets.hh \
+ portage_repository_entries.hh \
+ ebuild_entries.hh \
+ ebuild_flat_metadata_cache.hh \
+ eclass_mtimes.hh \
+ make_ebuild_repository.hh \
+ use_desc.hh \
+ portage_virtual_version_metadata.hh
+
+libpaludisportagerepository_la_SOURCES = \
+ glsa.cc \
+ portage_repository.cc \
+ portage_repository_profile_file.cc \
+ portage_repository_profile.cc \
+ portage_repository_exceptions.cc \
+ portage_repository_news.cc \
+ portage_repository_sets.cc \
+ portage_repository_entries.cc \
+ ebuild_entries.cc \
+ ebuild_flat_metadata_cache.cc \
+ eclass_mtimes.cc \
+ portage_repository_params.cc \
+ make_ebuild_repository.cc \
+ use_desc.cc \
+ portage_virtual_version_metadata.cc \
+ registration.cc \
+ $(paludis_repositories_portage_include_HEADERS)
+
+if MONOLITHIC
+
+libpaludisportagerepository_la_LIBADD = \
+ libpaludisportagerepositoryxmlthings.la \
+ $(DYNAMIC_LD_LIBS)
+
+else
+
+libpaludisportagerepository_la_LIBADD = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+portage_repository_TEST_SOURCES = portage_repository_TEST.cc
+
+if MONOLITHIC
+
+portage_repository_TEST_LDADD = \
+ libpaludisportagerepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+else
+
+portage_repository_TEST_LDADD = \
+ libpaludisportagerepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+portage_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+EXTRA_DIST = \
+ glsa.sr \
+ portage_repository_TEST.cc \
+ portage_repository_TEST_setup.sh \
+ portage_repository_TEST_cleanup.sh \
+ portage_repository_params-sr.hh \
+ portage_repository_params-sr.cc \
+ portage_repository_params.sr \
+ portage_repository-sr.hh \
+ portage_repository-sr.cc \
+ portage_repository.sr \
+ xml_things_TEST.cc \
+ xml_things_TEST_setup.sh \
+ xml_things_TEST_cleanup.sh
+
+BUILT_SOURCES = \
+ portage_repository_params-sr.hh \
+ portage_repository_params-sr.cc \
+ portage_repository-sr.hh \
+ portage_repository-sr.cc \
+ glsa-sr.hh \
+ glsa-sr.cc
+
+check_SCRIPTS = \
+ portage_repository_TEST_setup.sh portage_repository_TEST_cleanup.sh \
+ xml_things_TEST_setup.sh xml_things_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(top_srcdir)/ebuild/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ LD_LIBRARY_PATH="`$(top_srcdir)/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/portage/`" \
+ bash $(top_srcdir)/test/run_test.sh
+
+portage_repository-sr.hh : portage_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/portage_repository.sr > $@
+
+portage_repository-sr.cc : portage_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/portage_repository.sr > $@
+
+portage_repository_params-sr.hh : portage_repository_params.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/portage_repository_params.sr > $@
+
+portage_repository_params-sr.cc : portage_repository_params.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/portage_repository_params.sr > $@
+
+glsa-sr.hh : glsa.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/glsa.sr > $@
+
+glsa-sr.cc : glsa.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/glsa.sr > $@
+
+libpaludisportagerepositoryxmlthings_la_SOURCES = xml_things.cc xml_things.hh
+libpaludisportagerepositoryxmlthings_la_CXXFLAGS = $(AM_CXXFLAGS) @LIBXML2DEPS_CFLAGS@
+
+if MONOLITHIC
+
+libpaludisportagerepositoryxmlthings_la_LIBADD = @LIBXML2DEPS_LIBS@ \
+ $(DYNAMIC_LD_LIBS)
+
+else
+
+libpaludisportagerepositoryxmlthings_la_LIBADD = @LIBXML2DEPS_LIBS@ \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la
+
+endif
+
+libpaludisportagerepositoryxmlthings_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+if ENABLE_GLSA
+
+GLSA_TESTS = xml_things_TEST
+xml_things_TEST_SOURCES = xml_things_TEST.cc
+
+if MONOLITHIC
+
+xml_things_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludisportagerepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(top_builddir)/paludis/repositories/portage/libpaludisportagerepositoryxmlthings.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+else
+
+xml_things_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludisportagerepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environment/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+endif
+
+TESTS = portage_repository_TEST $(GLSA_TESTS)
+check_PROGRAMS = $(TESTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/0.18.0/paludis/repositories/portage/ebuild_entries.cc b/0.18.0/paludis/repositories/portage/ebuild_entries.cc
new file mode 100644
index 000000000..6d720ca78
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/ebuild_entries.cc
@@ -0,0 +1,526 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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/portage/ebuild_entries.hh>
+#include <paludis/repositories/portage/ebuild_flat_metadata_cache.hh>
+#include <paludis/repositories/portage/portage_repository.hh>
+
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/ebuild.hh>
+#include <paludis/environment.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/version_metadata.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <fstream>
+#include <list>
+#include <set>
+
+using namespace paludis;
+
+namespace paludis
+{
+ /**
+ * Implementation data for EbuildEntries.
+ *
+ * \ingroup grpportagerepository
+ */
+ template<>
+ struct Implementation<EbuildEntries>
+ {
+ const Environment * const environment;
+ PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ std::tr1::shared_ptr<EclassMtimes> eclass_mtimes;
+ time_t master_mtime;
+
+ Implementation(const Environment * const e, PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k),
+ eclass_mtimes(new EclassMtimes(k.eclassdirs)),
+ master_mtime(0)
+ {
+ FSEntry m(k.location / "metadata" / "timestamp");
+ if (m.exists())
+ master_mtime = m.mtime();
+ }
+ };
+}
+
+EbuildEntries::EbuildEntries(
+ const Environment * const e, PortageRepository * const p, const PortageRepositoryParams & k) :
+ PortageRepositoryEntries(".ebuild"),
+ PrivateImplementationPattern<EbuildEntries>(new
+ Implementation<EbuildEntries>(e, p, k))
+{
+}
+
+EbuildEntries::~EbuildEntries()
+{
+}
+
+std::tr1::shared_ptr<VersionMetadata>
+EbuildEntries::generate_version_metadata(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When generating version metadata for '" + stringify(q) + "-" + stringify(v) + "':");
+
+ std::tr1::shared_ptr<EbuildVersionMetadata> result(new EbuildVersionMetadata);
+
+ FSEntry ebuild_file(_imp->params.location / stringify(q.category) /
+ stringify(q.package) / (stringify(q.package) + "-" + stringify(v) + ".ebuild"));
+
+ FSEntry cache_file(_imp->params.cache);
+ cache_file /= stringify(q.category);
+ cache_file /= stringify(q.package) + "-" + stringify(v);
+
+ FSEntry write_cache_file(_imp->params.write_cache);
+ write_cache_file /= stringify(_imp->portage_repository->name());
+ write_cache_file /= stringify(q.category);
+ write_cache_file /= stringify(q.package) + "-" + stringify(v);
+
+ bool ok(false);
+ if (_imp->params.cache.basename() != "empty")
+ {
+
+ EbuildFlatMetadataCache metadata_cache(cache_file, ebuild_file, _imp->master_mtime,
+ _imp->eclass_mtimes, false);
+ if (metadata_cache.load(result))
+ ok = true;
+ }
+
+ if ((! ok) && _imp->params.write_cache.basename() != "empty")
+ {
+ EbuildFlatMetadataCache write_metadata_cache(write_cache_file, ebuild_file, _imp->master_mtime,
+ _imp->eclass_mtimes, true);
+ if (write_metadata_cache.load(result))
+ ok = true;
+ else if (write_cache_file.exists())
+ write_cache_file.unlink();
+ }
+
+ if (! ok)
+ {
+ if (_imp->params.cache.basename() != "empty")
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "No usable cache entry for '" + stringify(q) +
+ "-" + stringify(v) + "' in '" + stringify(_imp->portage_repository->name()) + "'");
+
+ PackageDatabaseEntry e(q, v, _imp->portage_repository->name());
+ EbuildMetadataCommand cmd(EbuildCommandParams::create()
+ .environment(_imp->environment)
+ .db_entry(&e)
+ .ebuild_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package))
+ .files_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .portdir(_imp->params.location)
+ .distdir(_imp->params.distdir)
+ .buildroot(_imp->params.buildroot));
+
+ if (! cmd())
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "No usable metadata for '" + stringify(q)
+ + "-" + stringify(v) + "' in '" + stringify(_imp->portage_repository->name()) + "'");
+
+ if (0 == ((result = cmd.metadata())))
+ throw InternalError(PALUDIS_HERE, "cmd.metadata() is zero pointer???");
+
+ if (_imp->params.write_cache.basename() != "empty" && result->eapi != "UNKNOWN")
+ {
+ EbuildFlatMetadataCache metadata_cache(write_cache_file, ebuild_file, _imp->master_mtime,
+ _imp->eclass_mtimes, false);
+ metadata_cache.save(result);
+ }
+ }
+
+ return result;
+}
+
+namespace
+{
+ class AAFinder :
+ private InstantiationPolicy<AAFinder, instantiation_method::NonCopyableTag>,
+ protected DepAtomVisitorTypes::ConstVisitor
+ {
+ private:
+ mutable std::list<const StringDepAtom *> _atoms;
+
+ protected:
+ void visit(const AllDepAtom * a)
+ {
+ std::for_each(a->begin(), a->end(), accept_visitor(
+ static_cast<DepAtomVisitorTypes::ConstVisitor *>(this)));
+ }
+
+ void visit(const AnyDepAtom *) PALUDIS_ATTRIBUTE((noreturn))
+ {
+ throw InternalError(PALUDIS_HERE, "Found unexpected AnyDepAtom");
+ }
+
+ void visit(const UseDepAtom * a)
+ {
+ std::for_each(a->begin(), a->end(), accept_visitor(
+ static_cast<DepAtomVisitorTypes::ConstVisitor *>(this)));
+ }
+
+ void visit(const PlainTextDepAtom * a)
+ {
+ _atoms.push_back(a);
+ }
+
+ void visit(const PackageDepAtom * a)
+ {
+ _atoms.push_back(a);
+ }
+
+ void visit(const BlockDepAtom * a)
+ {
+ _atoms.push_back(a);
+ }
+
+ public:
+ AAFinder(const std::tr1::shared_ptr<const DepAtom> a)
+ {
+ a->accept(static_cast<DepAtomVisitorTypes::ConstVisitor *>(this));
+ }
+
+ typedef std::list<const StringDepAtom *>::const_iterator Iterator;
+
+ Iterator begin()
+ {
+ return _atoms.begin();
+ }
+
+ Iterator end() const
+ {
+ return _atoms.end();
+ }
+ };
+
+}
+
+void
+EbuildEntries::install(const QualifiedPackageName & q, const VersionSpec & v,
+ const InstallOptions & o, std::tr1::shared_ptr<const PortageRepositoryProfile> p) const
+{
+ if (! _imp->portage_repository->has_version(q, v))
+ {
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since has_version failed");
+ }
+
+ std::tr1::shared_ptr<const VersionMetadata> metadata(_imp->portage_repository->version_metadata(q, v));
+
+ PackageDatabaseEntry e(q, v, _imp->portage_repository->name());
+
+ bool fetch_restrict(false), no_mirror(false);
+ {
+ std::list<std::string> restricts;
+ WhitespaceTokeniser::get_instance()->tokenise(
+ metadata->ebuild_interface->restrict_string, std::back_inserter(restricts));
+ fetch_restrict = (restricts.end() != std::find(restricts.begin(), restricts.end(), "fetch")) ||
+ (restricts.end() != std::find(restricts.begin(), restricts.end(), "nofetch"));
+ no_mirror = (restricts.end() != std::find(restricts.begin(), restricts.end(), "mirror")) ||
+ (restricts.end() != std::find(restricts.begin(), restricts.end(), "nomirror"));
+ }
+
+ std::string archives, all_archives, flat_src_uri;
+ {
+ std::set<std::string> already_in_archives;
+
+ /* make A and FLAT_SRC_URI */
+ std::tr1::shared_ptr<const DepAtom> f_atom(PortageDepParser::parse(metadata->ebuild_interface->src_uri,
+ PortageDepParserPolicy<PlainTextDepAtom, false>::get_instance()));
+ DepAtomFlattener f(_imp->params.environment, &e, f_atom);
+
+ for (DepAtomFlattener::Iterator ff(f.begin()), ff_end(f.end()) ; ff != ff_end ; ++ff)
+ {
+ std::string::size_type pos((*ff)->text().rfind('/'));
+ if (std::string::npos == pos)
+ {
+ if (already_in_archives.end() == already_in_archives.find((*ff)->text()))
+ {
+ archives.append((*ff)->text());
+ already_in_archives.insert((*ff)->text());
+ }
+ }
+ else
+ {
+ if (already_in_archives.end() == already_in_archives.find((*ff)->text().substr(pos + 1)))
+ {
+ archives.append((*ff)->text().substr(pos + 1));
+ already_in_archives.insert((*ff)->text().substr(pos + 1));
+ }
+ }
+ archives.append(" ");
+
+ /* add * mirror entries */
+ for (Environment::MirrorIterator
+ m(_imp->params.environment->begin_mirrors("*")),
+ m_end(_imp->params.environment->end_mirrors("*")) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + (*ff)->text().substr(pos + 1) + " ");
+
+ if (0 == (*ff)->text().compare(0, 9, "mirror://"))
+ {
+ std::string mirror((*ff)->text().substr(9));
+ std::string::size_type spos(mirror.find('/'));
+
+ if (std::string::npos == spos)
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since SRC_URI is broken");
+
+ if (! _imp->portage_repository->is_mirror(mirror.substr(0, spos)) &&
+ _imp->params.environment->begin_mirrors(mirror.substr(0, spos)) ==
+ _imp->params.environment->end_mirrors(mirror.substr(0, spos)))
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since SRC_URI references unknown mirror:// '" +
+ mirror.substr(0, spos) + "'");
+
+ for (Environment::MirrorIterator
+ m(_imp->params.environment->begin_mirrors(mirror.substr(0, spos))),
+ m_end(_imp->params.environment->end_mirrors(mirror.substr(0, spos))) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + mirror.substr(spos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(mirror.substr(0, spos))),
+ m_end(_imp->portage_repository->end_mirrors(mirror.substr(0, spos))) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + mirror.substr(spos + 1) + " ");
+ }
+ else
+ flat_src_uri.append((*ff)->text());
+ flat_src_uri.append(" ");
+
+ /* add mirror://gentoo/ entries */
+ std::string master_mirror(strip_trailing_string(stringify(_imp->portage_repository->name()), "x-"));
+ if (! no_mirror && _imp->portage_repository->is_mirror(master_mirror))
+ {
+ for (Environment::MirrorIterator
+ m(_imp->params.environment->begin_mirrors(master_mirror)),
+ m_end(_imp->params.environment->end_mirrors(master_mirror)) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + (*ff)->text().substr(pos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(master_mirror)),
+ m_end(_imp->portage_repository->end_mirrors(master_mirror)) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + (*ff)->text().substr(pos + 1) + " ");
+ }
+ }
+
+ /* make AA */
+ std::tr1::shared_ptr<const DepAtom> g_atom(PortageDepParser::parse(
+ metadata->ebuild_interface->src_uri,
+ PortageDepParserPolicy<PlainTextDepAtom, false>::get_instance()));
+ AAFinder g(g_atom);
+ std::set<std::string> already_in_all_archives;
+
+ for (AAFinder::Iterator gg(g.begin()), gg_end(g.end()) ; gg != gg_end ; ++gg)
+ {
+ std::string::size_type pos((*gg)->text().rfind('/'));
+ if (std::string::npos == pos)
+ {
+ if (already_in_all_archives.end() == already_in_all_archives.find((*gg)->text()))
+ {
+ all_archives.append((*gg)->text());
+ already_in_all_archives.insert((*gg)->text());
+ }
+ }
+ else
+ {
+ if (already_in_all_archives.end() == already_in_all_archives.find((*gg)->text().substr(pos + 1)))
+ {
+ all_archives.append((*gg)->text().substr(pos + 1));
+ already_in_all_archives.insert((*gg)->text().substr(pos + 1));
+ }
+ }
+ all_archives.append(" ");
+ }
+ }
+
+ /* Strip trailing space. Some ebuilds rely upon this. From kde-meta.eclass:
+ * [[ -n ${A/${TARBALL}/} ]] && unpack ${A/${TARBALL}/}
+ * Rather annoying.
+ */
+ archives = strip_trailing(archives, " ");
+ all_archives = strip_trailing(all_archives, " ");
+
+ /* make use */
+ std::string use;
+ {
+ std::set<UseFlagName> iuse;
+ WhitespaceTokeniser::get_instance()->tokenise(metadata->ebuild_interface->
+ iuse, create_inserter<UseFlagName>(std::inserter(iuse, iuse.begin())));
+ for (std::set<UseFlagName>::const_iterator iuse_it(iuse.begin()), iuse_end(iuse.end()) ;
+ iuse_it != iuse_end; ++iuse_it)
+ if (_imp->params.environment->query_use(*iuse_it, &e))
+ use += (*iuse_it).data() + " ";
+ }
+
+ use += p->environment_variable("ARCH") + " ";
+
+ /* add expand to use (iuse isn't reliable for use_expand things), and make the expand
+ * environment variables */
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > expand_vars(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator x(p->begin_use_expand()),
+ x_end(p->end_use_expand()) ; x != x_end ; ++x)
+ {
+ std::string lower_x;
+ std::transform(x->data().begin(), x->data().end(), std::back_inserter(lower_x), &::tolower);
+
+ expand_vars->insert(stringify(*x), "");
+
+ /* possible values from profile */
+ std::set<UseFlagName> possible_values;
+ WhitespaceTokeniser::get_instance()->tokenise(p->environment_variable(stringify(*x)),
+ create_inserter<UseFlagName>(std::inserter(possible_values, possible_values.end())));
+
+ /* possible values from environment */
+ std::tr1::shared_ptr<const UseFlagNameCollection> possible_values_from_env(_imp->params.environment->
+ known_use_expand_names(*x, &e));
+ for (UseFlagNameCollection::Iterator i(possible_values_from_env->begin()),
+ i_end(possible_values_from_env->end()) ; i != i_end ; ++i)
+ possible_values.insert(UseFlagName(stringify(*i).substr(lower_x.length() + 1)));
+
+ for (std::set<UseFlagName>::const_iterator u(possible_values.begin()), u_end(possible_values.end()) ;
+ u != u_end ; ++u)
+ {
+ if (! _imp->params.environment->query_use(UseFlagName(lower_x + "_" + stringify(*u)), &e))
+ continue;
+
+ use.append(lower_x + "_" + stringify(*u) + " ");
+
+ std::string value;
+ AssociativeCollection<std::string, std::string>::Iterator i(expand_vars->find(stringify(*x)));
+ if (expand_vars->end() != i)
+ {
+ value = i->second;
+ if (! value.empty())
+ value.append(" ");
+ expand_vars->erase(i);
+ }
+ value.append(stringify(*u));
+ expand_vars->insert(stringify(*x), value);
+ }
+ }
+
+ EbuildFetchCommand fetch_cmd(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .db_entry(&e)
+ .ebuild_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package))
+ .files_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .portdir(_imp->params.location)
+ .distdir(_imp->params.distdir)
+ .buildroot(_imp->params.buildroot),
+
+ EbuildFetchCommandParams::create()
+ .a(archives)
+ .aa(all_archives)
+ .use(use)
+ .use_expand(join(p->begin_use_expand(), p->end_use_expand(), " "))
+ .expand_vars(expand_vars)
+ .flat_src_uri(flat_src_uri)
+ .root(stringify(_imp->params.root) + "/")
+ .profiles(_imp->params.profiles)
+ .no_fetch(fetch_restrict)
+ .safe_resume(o.safe_resume));
+
+ fetch_cmd();
+
+ if (o.fetch_only)
+ return;
+
+ EbuildInstallCommand install_cmd(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .db_entry(&e)
+ .ebuild_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package))
+ .files_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .portdir(_imp->params.location)
+ .distdir(_imp->params.distdir)
+ .buildroot(_imp->params.buildroot),
+
+ EbuildInstallCommandParams::create()
+ .use(use)
+ .a(archives)
+ .aa(all_archives)
+ .use_expand(join(p->begin_use_expand(), p->end_use_expand(), " "))
+ .expand_vars(expand_vars)
+ .root(stringify(_imp->params.root) + "/")
+ .profiles(_imp->params.profiles)
+ .disable_cfgpro(o.no_config_protect)
+ .debug_build(o.debug_build)
+ .slot(SlotName(metadata->slot)));
+
+ install_cmd();
+}
+
+std::string
+EbuildEntries::get_environment_variable(const QualifiedPackageName & q,
+ const VersionSpec & v, const std::string & var,
+ std::tr1::shared_ptr<const PortageRepositoryProfile>) const
+{
+ PackageDatabaseEntry for_package(q, v, _imp->portage_repository->name());
+
+ EbuildVariableCommand cmd(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .db_entry(&for_package)
+ .ebuild_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package))
+ .files_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .portdir(_imp->params.location)
+ .distdir(_imp->params.distdir)
+ .buildroot(_imp->params.buildroot),
+
+ var);
+
+ if (! cmd())
+ throw EnvironmentVariableActionError("Couldn't get environment variable '" +
+ stringify(var) + "' for package '" + stringify(for_package) + "'");
+
+ return cmd.result();
+}
+
+std::tr1::shared_ptr<PortageRepositoryEntries>
+EbuildEntries::make_ebuild_entries(
+ const Environment * const e, PortageRepository * const r, const PortageRepositoryParams & p)
+{
+ return std::tr1::shared_ptr<PortageRepositoryEntries>(new EbuildEntries(e, r, p));
+}
+
diff --git a/0.18.0/paludis/repositories/portage/ebuild_entries.hh b/0.18.0/paludis/repositories/portage/ebuild_entries.hh
new file mode 100644
index 000000000..711640598
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/ebuild_entries.hh
@@ -0,0 +1,70 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_PORTAGE_REPOSITORY_EBUILD_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_EBUILD_METADATA_HH 1
+
+#include <paludis/repositories/portage/portage_repository_entries.hh>
+#include <paludis/repositories/portage/portage_repository_params.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+/** \file
+ * Declaration for the EbuildEntries class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class FSEntry;
+ class PortageRepository;
+
+ /**
+ * PortageRepositoryEntries handler for ebuilds.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE EbuildEntries :
+ public PortageRepositoryEntries,
+ private PrivateImplementationPattern<EbuildEntries>
+ {
+ public:
+ static std::tr1::shared_ptr<PortageRepositoryEntries>
+ make_ebuild_entries(const Environment * const,
+ PortageRepository * const, const PortageRepositoryParams &);
+
+ EbuildEntries(const Environment * const,
+ PortageRepository * const portage_repository,
+ const PortageRepositoryParams &);
+
+ virtual ~EbuildEntries();
+
+ virtual std::tr1::shared_ptr<VersionMetadata> generate_version_metadata(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::string get_environment_variable(const QualifiedPackageName &,
+ const VersionSpec &, const std::string & var,
+ std::tr1::shared_ptr<const PortageRepositoryProfile>) const;
+
+ virtual void install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &, std::tr1::shared_ptr<const PortageRepositoryProfile>) const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.cc b/0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.cc
new file mode 100644
index 000000000..e5873e4ed
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.cc
@@ -0,0 +1,147 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "ebuild_flat_metadata_cache.hh"
+#include <paludis/util/log.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/join.hh>
+#include <fstream>
+#include <set>
+#include <list>
+
+using namespace paludis;
+
+EbuildFlatMetadataCache::EbuildFlatMetadataCache(const FSEntry & f,
+ const FSEntry & e, time_t t, std::tr1::shared_ptr<const EclassMtimes> m, bool s) :
+ _filename(f),
+ _ebuild(e),
+ _master_mtime(t),
+ _eclass_mtimes(m),
+ _silent(s)
+{
+}
+
+bool
+EbuildFlatMetadataCache::load(std::tr1::shared_ptr<EbuildVersionMetadata> result)
+{
+ Context context("When loading version metadata to '" + stringify(_filename) + "':");
+
+ std::ifstream cache(stringify(_filename).c_str());
+ std::string line;
+
+ if (cache)
+ {
+ std::getline(cache, line); result->build_depend_string = line;
+ std::getline(cache, line); result->run_depend_string = line;
+ std::getline(cache, line); result->slot = SlotName(line);
+ std::getline(cache, line); result->src_uri = line;
+ std::getline(cache, line); result->restrict_string = line;
+ std::getline(cache, line); result->homepage = line;
+ std::getline(cache, line); result->license_string = line;
+ std::getline(cache, line); result->description = line;
+ std::getline(cache, line); result->keywords = line;
+ std::getline(cache, line); result->inherited = line;
+ std::getline(cache, line); result->iuse = line;
+ std::getline(cache, line);
+ std::getline(cache, line); result->post_depend_string = line;
+ std::getline(cache, line); result->provide_string = line;
+ std::getline(cache, line); result->eapi = line;
+
+ // check mtimes
+ time_t cache_time(std::max(_master_mtime, _filename.mtime()));
+ bool ok = true;
+
+ if (_ebuild.mtime() > cache_time)
+ ok = false;
+ else
+ {
+ std::set<std::string> inherits;
+ WhitespaceTokeniser::get_instance()->tokenise(
+ stringify(result->inherited),
+ std::inserter(inherits, inherits.end()));
+
+ for (std::set<std::string>::const_iterator i(inherits.begin()),
+ i_end(inherits.end()) ; i != i_end ; ++i)
+ if (_eclass_mtimes->mtime(*i) > cache_time)
+ {
+ ok = false;
+ break;
+ }
+ }
+
+ if (! ok)
+ Log::get_instance()->message(ll_warning, lc_no_context, "Stale cache file at '"
+ + stringify(_filename) + "'");
+
+ return ok;
+ }
+ else
+ {
+ Log::get_instance()->message(_silent ? ll_debug : ll_warning, lc_no_context,
+ "Couldn't use the cache file at '" + stringify(_filename) + "'");
+ return false;
+ }
+}
+
+namespace
+{
+ template <typename T_>
+ std::string normalise(const T_ & s)
+ {
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(stringify(s), std::back_inserter(tokens));
+ return join(tokens.begin(), tokens.end(), " ");
+ }
+}
+
+void
+EbuildFlatMetadataCache::save(std::tr1::shared_ptr<const EbuildVersionMetadata> v)
+{
+ Context context("When saving version metadata to '" + stringify(_filename) + "':");
+
+ _filename.dirname().dirname().mkdir();
+ _filename.dirname().mkdir();
+ std::ofstream cache(stringify(_filename).c_str());
+
+ if (cache)
+ {
+ cache << normalise(v->build_depend_string) << std::endl;
+ cache << normalise(v->run_depend_string) << std::endl;
+ cache << normalise(v->slot) << std::endl;
+ cache << normalise(v->src_uri) << std::endl;
+ cache << normalise(v->restrict_string) << std::endl;
+ cache << normalise(v->homepage) << std::endl;
+ cache << normalise(v->license_string) << std::endl;
+ cache << normalise(v->description) << std::endl;
+ cache << normalise(v->keywords) << std::endl;
+ cache << normalise(v->inherited) << std::endl;
+ cache << normalise(v->iuse) << std::endl;
+ cache << std::endl;
+ cache << normalise(v->post_depend_string) << std::endl;
+ cache << normalise(v->provide_string) << std::endl;
+ cache << normalise(v->eapi) << std::endl;
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Couldn't write cache file to '" + stringify(_filename) + "'");
+ }
+
+}
+
diff --git a/0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.hh b/0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.hh
new file mode 100644
index 000000000..34abf6e2c
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/ebuild_flat_metadata_cache.hh
@@ -0,0 +1,67 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_EBUILD_FLAT_METADATA_CACHE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_EBUILD_FLAT_METADATA_CACHE_HH 1
+
+#include <paludis/ebuild.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/version_metadata.hh>
+#include <paludis/repositories/portage/eclass_mtimes.hh>
+
+namespace paludis
+{
+ /**
+ * Implements flat file metadata cache handling for a PortageRepository
+ * using EbuildEntries.
+ *
+ * \see EbuildEntries
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class EbuildFlatMetadataCache
+ {
+ private:
+ const FSEntry & _filename;
+ const FSEntry & _ebuild;
+ time_t _master_mtime;
+ std::tr1::shared_ptr<const EclassMtimes> _eclass_mtimes;
+ bool _silent;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EbuildFlatMetadataCache(const FSEntry & filename, const FSEntry & ebuild,
+ time_t master_mtime, std::tr1::shared_ptr<const EclassMtimes> eclass_mtimes, bool silent);
+
+ ///\}
+
+ ///\name Cache operations
+ ///\{
+
+ bool load(std::tr1::shared_ptr<EbuildVersionMetadata>);
+ void save(std::tr1::shared_ptr<const EbuildVersionMetadata>);
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/eclass_mtimes.cc b/0.18.0/paludis/repositories/portage/eclass_mtimes.cc
new file mode 100644
index 000000000..abc7e2018
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/eclass_mtimes.cc
@@ -0,0 +1,68 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "eclass_mtimes.hh"
+#include <paludis/hashed_containers.hh>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<EclassMtimes>
+ {
+ std::tr1::shared_ptr<const FSEntryCollection> eclass_dirs;
+ mutable MakeHashedMap<std::string, time_t>::Type eclass_mtimes;
+
+ Implementation(std::tr1::shared_ptr<const FSEntryCollection> d) :
+ eclass_dirs(d)
+ {
+ }
+ };
+}
+
+EclassMtimes::EclassMtimes(std::tr1::shared_ptr<const FSEntryCollection> d) :
+ PrivateImplementationPattern<EclassMtimes>(new Implementation<EclassMtimes>(d))
+{
+}
+
+EclassMtimes::~EclassMtimes()
+{
+}
+
+time_t
+EclassMtimes::mtime(const std::string & e) const
+{
+ MakeHashedMap<std::string, time_t>::Type::const_iterator i(_imp->eclass_mtimes.find(e));
+ if (i != _imp->eclass_mtimes.end())
+ return i->second;
+
+ time_t r(0);
+ for (FSEntryCollection::Iterator d(_imp->eclass_dirs->begin()),
+ d_end(_imp->eclass_dirs->end()) ; d != d_end ; ++d)
+ {
+ FSEntry f(*d / (e + ".eclass"));
+ if (f.exists())
+ r = std::max(r, f.mtime());
+ }
+
+ _imp->eclass_mtimes.insert(std::make_pair(e, r));
+ return r;
+}
+
diff --git a/0.18.0/paludis/repositories/portage/eclass_mtimes.hh b/0.18.0/paludis/repositories/portage/eclass_mtimes.hh
new file mode 100644
index 000000000..1bfdc4630
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/eclass_mtimes.hh
@@ -0,0 +1,55 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_ECLASS_MTIMES_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_ECLASS_MTIMES_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/collection.hh>
+
+namespace paludis
+{
+ /**
+ * Holds an eclass mtimes cache for a PortageRepository.
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class EclassMtimes :
+ private PrivateImplementationPattern<EclassMtimes>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EclassMtimes(std::tr1::shared_ptr<const FSEntryCollection>);
+ ~EclassMtimes();
+
+ ///\}
+
+ /**
+ * Fetch the mtime for a given eclass.
+ */
+ time_t mtime(const std::string &) const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/glsa.cc b/0.18.0/paludis/repositories/portage/glsa.cc
new file mode 100644
index 000000000..4bdcb0960
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/glsa.cc
@@ -0,0 +1,251 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "glsa.hh"
+#include <paludis/util/iterator.hh>
+#include <paludis/util/stringify.hh>
+#include <list>
+#include <dlfcn.h>
+#include <stdint.h>
+#include "config.h"
+
+#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
+
+using namespace paludis;
+
+#include "glsa-sr.cc"
+
+#ifdef MONOLITHIC
+# include <paludis/repositories/portage/xml_things.hh>
+#endif
+
+namespace paludis
+{
+ template<>
+ struct Implementation<GLSAPackage>
+ {
+ QualifiedPackageName name;
+ std::list<UseFlagName> archs;
+ std::list<GLSARange> unaffected;
+ std::list<GLSARange> vulnerable;
+
+ Implementation(const QualifiedPackageName & n) :
+ name(n)
+ {
+ }
+ };
+
+ template<>
+ struct Implementation<GLSA>
+ {
+ std::string id;
+ std::string title;
+ std::list<std::tr1::shared_ptr<const GLSAPackage> > packages;
+ };
+}
+
+GLSAPackage::GLSAPackage(const QualifiedPackageName & n) :
+ PrivateImplementationPattern<GLSAPackage>(new Implementation<GLSAPackage>(n))
+{
+}
+
+GLSAPackage::~GLSAPackage()
+{
+}
+
+GLSAPackage::ArchsIterator
+GLSAPackage::begin_archs() const
+{
+ return ArchsIterator(_imp->archs.begin());
+}
+
+GLSAPackage::ArchsIterator
+GLSAPackage::end_archs() const
+{
+ return ArchsIterator(_imp->archs.end());
+}
+
+void
+GLSAPackage::add_arch(const UseFlagName & n)
+{
+ _imp->archs.push_back(n);
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::begin_unaffected() const
+{
+ return RangesIterator(_imp->unaffected.begin());
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::end_unaffected() const
+{
+ return RangesIterator(_imp->unaffected.end());
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::begin_vulnerable() const
+{
+ return RangesIterator(_imp->vulnerable.begin());
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::end_vulnerable() const
+{
+ return RangesIterator(_imp->vulnerable.end());
+}
+
+void
+GLSAPackage::add_unaffected(const GLSARange & r)
+{
+ _imp->unaffected.push_back(r);
+}
+
+void
+GLSAPackage::add_vulnerable(const GLSARange & r)
+{
+ _imp->vulnerable.push_back(r);
+}
+
+QualifiedPackageName
+GLSAPackage::name() const
+{
+ return _imp->name;
+}
+
+GLSA::GLSA() :
+ PrivateImplementationPattern<GLSA>(new Implementation<GLSA>)
+{
+}
+
+GLSA::~GLSA()
+{
+}
+
+GLSA::PackagesIterator
+GLSA::begin_packages() const
+{
+ return PackagesIterator(indirect_iterator<const GLSAPackage>(_imp->packages.begin()));
+}
+
+GLSA::PackagesIterator
+GLSA::end_packages() const
+{
+ return PackagesIterator(indirect_iterator<const GLSAPackage>(_imp->packages.end()));
+}
+
+void
+GLSA::add_package(std::tr1::shared_ptr<const GLSAPackage> p)
+{
+ _imp->packages.push_back(p);
+}
+
+void
+GLSA::set_id(const std::string & s)
+{
+ _imp->id = s;
+}
+
+void
+GLSA::set_title(const std::string & s)
+{
+ _imp->title = s;
+}
+
+std::string
+GLSA::id() const
+{
+ return _imp->id;
+}
+
+std::string
+GLSA::title() const
+{
+ return _imp->title;
+}
+
+#ifndef MONOLITHIC
+
+namespace
+{
+ struct LibXMLHandle
+ {
+ void * handle;
+ std::tr1::shared_ptr<GLSA> (* create_glsa_from_xml_file_handle)(const std::string &);
+
+ LibXMLHandle() :
+ handle(0),
+ create_glsa_from_xml_file_handle(0)
+ {
+ }
+
+ ~LibXMLHandle()
+ {
+ if (0 != handle)
+ dlclose(handle);
+ }
+
+ } libxmlhandle;
+}
+
+#endif
+
+std::tr1::shared_ptr<GLSA>
+GLSA::create_from_xml_file(const std::string & filename)
+{
+#if ENABLE_GLSA
+# ifdef MONOLITHIC
+
+# else
+ if (0 == libxmlhandle.handle)
+ libxmlhandle.handle = dlopen("libpaludisportagerepositoryxmlthings.so",
+ RTLD_NOW | RTLD_GLOBAL);
+ if (0 == libxmlhandle.handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' due to error '"
+ + stringify(dlerror()) + "' when dlopen(libpaludisportagerepositoryxmlthings.so)");
+
+ if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
+ libxmlhandle.create_glsa_from_xml_file_handle = STUPID_CAST(std::tr1::shared_ptr<GLSA> (*)(const std::string &),
+ dlsym(libxmlhandle.handle, "create_glsa_from_xml_file"));
+ if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' due to error '"
+ + stringify(dlerror()) + "' when dlsym(libpaludisportagerepositoryxmlthings.so, create_glsa_from_xml_file)");
+
+# endif
+#else
+# ifndef MONOLITHIC
+ /* avoid noreturn warning */
+ if (0 == libxmlhandle.handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' because Paludis was built "
+ "without GLSA support");
+# endif
+#endif
+
+#ifdef MONOLITHIC
+ return create_glsa_from_xml_file(filename);
+#else
+ return (*libxmlhandle.create_glsa_from_xml_file_handle)(filename);
+#endif
+}
+
+GLSAError::GLSAError(const std::string & msg, const std::string & filename) throw () :
+ ConfigurationError("GLSA error: " + msg + (filename.empty() ? "" : " in file " + filename))
+{
+}
+
diff --git a/0.18.0/paludis/repositories/portage/glsa.hh b/0.18.0/paludis/repositories/portage/glsa.hh
new file mode 100644
index 000000000..f85507895
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/glsa.hh
@@ -0,0 +1,113 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_GLSA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_GLSA_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/sr.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+#include <string>
+
+namespace paludis
+{
+
+#include <paludis/repositories/portage/glsa-sr.hh>
+
+ /**
+ * Thrown if a bad GLSA is found.
+ *
+ * \ingroup grpexceptions
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE GLSAError :
+ public ConfigurationError
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ GLSAError(const std::string & message,
+ const std::string & filename = "") throw ();
+
+ ///\}
+ };
+
+ /**
+ * Represents a package entry in a GLSA.
+ *
+ * \see GLSA
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE GLSAPackage :
+ private PrivateImplementationPattern<GLSAPackage>
+ {
+ public:
+ GLSAPackage(const QualifiedPackageName & name);
+ ~GLSAPackage();
+
+ typedef libwrapiter::ForwardIterator<GLSAPackage, const UseFlagName> ArchsIterator;
+ ArchsIterator begin_archs() const;
+ ArchsIterator end_archs() const;
+ void add_arch(const UseFlagName &);
+
+ typedef libwrapiter::ForwardIterator<GLSAPackage, const GLSARange> RangesIterator;
+ RangesIterator begin_unaffected() const;
+ RangesIterator end_unaffected() const;
+ RangesIterator begin_vulnerable() const;
+ RangesIterator end_vulnerable() const;
+ void add_unaffected(const GLSARange &);
+ void add_vulnerable(const GLSARange &);
+
+ QualifiedPackageName name() const;
+ };
+
+ /**
+ * Represents a GLSA (security advisory).
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE GLSA :
+ private PrivateImplementationPattern<GLSA>
+ {
+ public:
+ GLSA();
+ ~GLSA();
+
+ static std::tr1::shared_ptr<GLSA> create_from_xml_file(const std::string & filename);
+
+ typedef libwrapiter::ForwardIterator<GLSA, const GLSAPackage> PackagesIterator;
+ PackagesIterator begin_packages() const;
+ PackagesIterator end_packages() const;
+ void add_package(std::tr1::shared_ptr<const GLSAPackage>);
+
+ void set_id(const std::string &);
+ std::string id() const;
+
+ void set_title(const std::string &);
+ std::string title() const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/glsa.sr b/0.18.0/paludis/repositories/portage/glsa.sr
new file mode 100644
index 000000000..359ffeeff
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/glsa.sr
@@ -0,0 +1,8 @@
+make_class_GLSARange()
+{
+ key op std::string;
+ # not a version, may be something like 1.3*
+ key version std::string;
+
+ allow_named_args;
+}
diff --git a/0.18.0/paludis/repositories/portage/make_ebuild_repository.cc b/0.18.0/paludis/repositories/portage/make_ebuild_repository.cc
new file mode 100644
index 000000000..87906e598
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/make_ebuild_repository.cc
@@ -0,0 +1,165 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "make_ebuild_repository.hh"
+#include <paludis/util/log.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/repositories/portage/portage_repository_exceptions.hh>
+
+using namespace paludis;
+
+std::tr1::shared_ptr<PortageRepository>
+paludis::make_ebuild_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
+ m->find("repo_file")->second);
+
+ Context context("When making ebuild repository from repo_file '" + repo_file + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw PortageRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::tr1::shared_ptr<FSEntryCollection> profiles(new FSEntryCollection::Concrete);
+ if (m->end() != m->find("profiles"))
+ WhitespaceTokeniser::get_instance()->tokenise(m->find("profiles")->second,
+ create_inserter<FSEntry>(std::back_inserter(*profiles)));
+ if (m->end() != m->find("profile") && ! m->find("profile")->second.empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Key 'profile' in '" + repo_file + "' is deprecated, "
+ "use 'profiles = " + m->find("profile")->second + "' instead");
+ if (profiles->empty())
+ profiles->append(m->find("profile")->second);
+ else
+ throw PortageRepositoryConfigurationError("Both 'profile' and 'profiles' keys are present");
+ }
+ if (profiles->empty())
+ throw PortageRepositoryConfigurationError("No profiles have been specified");
+
+ std::tr1::shared_ptr<FSEntryCollection> eclassdirs(new FSEntryCollection::Concrete);
+ if (m->end() != m->find("eclassdirs"))
+ WhitespaceTokeniser::get_instance()->tokenise(m->find("eclassdirs")->second,
+ create_inserter<FSEntry>(std::back_inserter(*eclassdirs)));
+ if (m->end() != m->find("eclassdir") && ! m->find("eclassdir")->second.empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Key 'eclassdir' in '" + repo_file + "' is deprecated, "
+ "use 'eclassdirs = " + m->find("eclassdir")->second + "' instead");
+ if (eclassdirs->empty())
+ eclassdirs->append(m->find("eclassdir")->second);
+ else
+ throw PortageRepositoryConfigurationError("Both 'eclassdir' and 'eclassdirs' keys are present");
+ }
+ if (eclassdirs->empty())
+ eclassdirs->append(location + "/eclass");
+
+ std::string distdir;
+ if (m->end() == m->find("distdir") || ((distdir = m->find("distdir")->second)).empty())
+ distdir = location + "/distfiles";
+
+ std::string setsdir;
+ if (m->end() == m->find("setsdir") || ((setsdir = m->find("setsdir")->second)).empty())
+ setsdir = location + "/sets";
+
+ std::string securitydir;
+ if (m->end() == m->find("securitydir") || ((securitydir = m->find("securitydir")->second)).empty())
+ securitydir = location + "/metadata/glsa";
+
+ std::string newsdir;
+ if (m->end() == m->find("newsdir") || ((newsdir = m->find("newsdir")->second)).empty())
+ newsdir = location + "/metadata/news";
+
+ std::string cache;
+ if (m->end() == m->find("cache") || ((cache = m->find("cache")->second)).empty())
+ {
+ cache = location + "/metadata/cache";
+ if (! FSEntry(cache).exists())
+ cache = "/var/empty";
+ }
+
+ std::string write_cache;
+ if (m->end() == m->find("write_cache") || ((write_cache = m->find("write_cache")->second)).empty())
+ write_cache = "/var/empty";
+
+ std::string names_cache;
+ if (m->end() == m->find("names_cache") || ((names_cache = m->find("names_cache")->second)).empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The names_cache key is not set in '"
+ + repo_file + "'. You should read http://paludis.pioto.org/cachefiles.html and select an "
+ "appropriate value.");
+ names_cache = "/var/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;
+
+ if (m->end() != m->find("sync_exclude"))
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The sync_exclude key in '"
+ + repo_file + "' is deprecated in favour of sync_options = --exclude-from=");
+ if (! sync_options.empty())
+ sync_options += " ";
+ sync_options += "--exclude-from='" + m->find("sync_exclude")->second + "'";
+ }
+
+ std::string root;
+ if (m->end() == m->find("root") || ((root = m->find("root")->second)).empty())
+ root = "/";
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = "/var/tmp/paludis";
+
+ return std::tr1::shared_ptr<PortageRepository>(new PortageRepository(PortageRepositoryParams::create()
+ .entry_format("ebuild")
+ .environment(env)
+ .location(location)
+ .profiles(profiles)
+ .cache(cache)
+ .write_cache(write_cache)
+ .names_cache(names_cache)
+ .eclassdirs(eclassdirs)
+ .distdir(distdir)
+ .pkgdir(FSEntry("/var/empty"))
+ .securitydir(securitydir)
+ .setsdir(setsdir)
+ .newsdir(newsdir)
+ .sync(sync)
+ .sync_options(sync_options)
+ .root(root)
+ .buildroot(buildroot)));
+}
+
+std::tr1::shared_ptr<Repository>
+paludis::make_ebuild_repository_wrapped(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ return make_ebuild_repository(env, m);
+}
+
diff --git a/0.18.0/paludis/repositories/portage/make_ebuild_repository.hh b/0.18.0/paludis/repositories/portage/make_ebuild_repository.hh
new file mode 100644
index 000000000..3fb748411
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/make_ebuild_repository.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_MAKE_EBUILD_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_MAKE_EBUILD_REPOSITORY_HH 1
+
+#include <paludis/repositories/portage/portage_repository.hh>
+
+namespace paludis
+{
+ /**
+ * Create an ebuild format repository.
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ */
+ std::tr1::shared_ptr<PortageRepository>
+ make_ebuild_repository(
+ Environment * const,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >) PALUDIS_VISIBLE;
+
+ std::tr1::shared_ptr<Repository>
+ make_ebuild_repository_wrapped(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m);
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository.cc b/0.18.0/paludis/repositories/portage/portage_repository.cc
new file mode 100644
index 000000000..ff093a8d0
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository.cc
@@ -0,0 +1,1160 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <paludis/repositories/portage/portage_repository.hh>
+#include <paludis/repositories/portage/portage_repository_profile.hh>
+#include <paludis/repositories/portage/portage_repository_news.hh>
+#include <paludis/repositories/portage/portage_repository_sets.hh>
+#include <paludis/repositories/portage/portage_repository_exceptions.hh>
+#include <paludis/repositories/portage/portage_repository_entries.hh>
+#include <paludis/repositories/portage/portage_virtual_version_metadata.hh>
+#include <paludis/repositories/portage/use_desc.hh>
+
+#include <paludis/config_file.hh>
+#include <paludis/dep_atom.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/environment.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/match_package.hh>
+#include <paludis/package_database.hh>
+#include <paludis/package_database_entry.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/repository_name_cache.hh>
+#include <paludis/syncer.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/random.hh>
+#include <paludis/util/save.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <map>
+#include <fstream>
+#include <functional>
+#include <algorithm>
+#include <vector>
+#include <limits>
+
+#include <strings.h>
+#include <ctype.h>
+
+/** \file
+ * Implementation of PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+
+using namespace paludis;
+
+#include <paludis/repositories/portage/portage_repository-sr.cc>
+
+namespace paludis
+{
+ /// Map for versions.
+ typedef MakeHashedMap<QualifiedPackageName, std::tr1::shared_ptr<VersionSpecCollection> >::Type VersionsMap;
+
+ /// Map for repository masks.
+ typedef MakeHashedMap<QualifiedPackageName, std::list<std::tr1::shared_ptr<const PackageDepAtom> > >::Type RepositoryMaskMap;
+
+ /// Map for categories.
+ typedef MakeHashedMap<CategoryNamePart, bool>::Type CategoryMap;
+
+ /// Map for packages.
+ typedef MakeHashedMap<QualifiedPackageName, bool>::Type PackagesMap;
+
+ /// Map for mirrors.
+ typedef MakeHashedMultiMap<std::string, std::string>::Type MirrorMap;
+
+ /// Map for metadata.
+ typedef MakeHashedMap<std::pair<QualifiedPackageName, VersionSpec>,
+ std::tr1::shared_ptr<VersionMetadata> >::Type MetadataMap;
+
+ /// Map for virtuals.
+ typedef MakeHashedMap<QualifiedPackageName, std::tr1::shared_ptr<const PackageDepAtom> >::Type VirtualsMap;
+
+ typedef std::list<PortageRepositoryProfilesDescLine> ProfilesDesc;
+
+ /**
+ * Implementation data for a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+ template <>
+ struct Implementation<PortageRepository>
+ {
+ /// Our parameters
+ const PortageRepositoryParams params;
+
+ /// Have we loaded our category names?
+ mutable bool has_category_names;
+
+ /// Our category names, and whether we have a fully loaded list
+ /// of package names for that category.
+ mutable CategoryMap category_names;
+
+ /// Our package names, and whether we have a fully loaded list of
+ /// version specs for that category.
+ mutable PackagesMap package_names;
+
+ /// Our version specs for each package.
+ mutable VersionsMap version_specs;
+
+ /// Metadata cache.
+ mutable MetadataMap metadata;
+
+ /// Repository mask.
+ mutable RepositoryMaskMap repo_mask;
+
+ /// Have repository mask?
+ mutable bool has_repo_mask;
+
+ /// Have virtual names?
+ mutable bool has_virtuals;
+
+ /// Arch flags
+ mutable std::tr1::shared_ptr<UseFlagNameCollection> arch_flags;
+
+ /// Do we have mirrors?
+ mutable bool has_mirrors;
+
+ /// Mirrors.
+ mutable MirrorMap mirrors;
+
+ /// Constructor.
+ Implementation(PortageRepository * const, const PortageRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Load profiles, if we haven't already.
+ inline void need_profiles() const;
+
+ void need_profiles_desc() const;
+
+ /// Our profile handler.
+ mutable std::tr1::shared_ptr<PortageRepositoryProfile> profile_ptr;
+
+ /// Our news handler.
+ mutable std::tr1::shared_ptr<PortageRepositoryNews> news_ptr;
+
+ /// Our sets handler.
+ mutable std::tr1::shared_ptr<PortageRepositorySets> sets_ptr;
+
+ /// Our metadata handler.
+ mutable std::tr1::shared_ptr<PortageRepositoryEntries> entries_ptr;
+
+ /// Our virtuals
+ mutable VirtualsMap our_virtuals;
+
+ /// Have we loaded our virtuals?
+ bool has_our_virtuals;
+
+ mutable bool has_profiles_desc;
+
+ mutable ProfilesDesc profiles_desc;
+
+ std::tr1::shared_ptr<RepositoryNameCache> names_cache;
+
+ mutable std::tr1::shared_ptr<UseDesc> use_desc;
+
+ PortageRepository * const repo;
+ };
+
+ Implementation<PortageRepository>::Implementation(PortageRepository * const r,
+ const PortageRepositoryParams & p) :
+ params(p),
+ has_category_names(false),
+ has_repo_mask(false),
+ has_virtuals(false),
+ has_mirrors(false),
+ news_ptr(new PortageRepositoryNews(params.environment, r, p)),
+ sets_ptr(new PortageRepositorySets(params.environment, r, p)),
+ entries_ptr(PortageRepositoryEntriesMaker::get_instance()->find_maker(
+ params.entry_format)(params.environment, r, p)),
+ has_our_virtuals(false),
+ has_profiles_desc(false),
+ names_cache(new RepositoryNameCache(p.names_cache, r)),
+ repo(r)
+ {
+ }
+
+ Implementation<PortageRepository>::~Implementation()
+ {
+ }
+
+ void
+ Implementation<PortageRepository>::need_profiles() const
+ {
+ if (profile_ptr)
+ return;
+
+ profile_ptr.reset(new PortageRepositoryProfile(
+ params.environment, repo->name(), *params.profiles));
+ }
+
+ void
+ Implementation<PortageRepository>::need_profiles_desc() const
+ {
+ if (has_profiles_desc)
+ return;
+
+ Context context("When loading profiles.desc:");
+
+ LineConfigFile p(params.location / "profiles" / "profiles.desc");
+ for (LineConfigFile::Iterator line(p.begin()), line_end(p.end()) ; line != line_end ; ++line)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line,
+ std::back_inserter(tokens));
+ if (tokens.size() < 3)
+ continue;
+
+ FSEntryCollection::Concrete profiles;
+ profiles.push_back(params.location / "profiles" / tokens.at(1));
+ profiles_desc.push_back(PortageRepositoryProfilesDescLine::create()
+ .arch(tokens.at(0))
+ .path(*profiles.begin())
+ .status(tokens.at(2))
+ .profile(std::tr1::shared_ptr<PortageRepositoryProfile>(new PortageRepositoryProfile(
+ params.environment, repo->name(), profiles))));
+ }
+
+ has_profiles_desc = true;
+ }
+}
+
+PortageRepository::PortageRepository(const PortageRepositoryParams & p) :
+ Repository(PortageRepository::fetch_repo_name(stringify(p.location)),
+ RepositoryCapabilities::create()
+ .mask_interface(this)
+ .installable_interface(this)
+ .installed_interface(0)
+ .news_interface(this)
+ .sets_interface(this)
+ .syncable_interface(this)
+ .uninstallable_interface(0)
+ .use_interface(this)
+ .world_interface(0)
+ .environment_variable_interface(this)
+ .mirrors_interface(this)
+ .virtuals_interface(this)
+ .provides_interface(0)
+ .contents_interface(0)
+ .config_interface(0)
+ .destination_interface(0),
+ p.entry_format),
+ PrivateImplementationPattern<PortageRepository>(new Implementation<PortageRepository>(this, p))
+{
+ // the info_vars and info_pkgs info is only added on demand, since it's
+ // fairly slow to calculate.
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->params.location));
+ config_info->add_kv("profiles", join(_imp->params.profiles->begin(),
+ _imp->params.profiles->end(), " "));
+ config_info->add_kv("eclassdirs", join(_imp->params.eclassdirs->begin(),
+ _imp->params.eclassdirs->end(), " "));
+ config_info->add_kv("cache", stringify(_imp->params.cache));
+ config_info->add_kv("write_cache", stringify(_imp->params.write_cache));
+ config_info->add_kv("names_cache", stringify(_imp->params.names_cache));
+ config_info->add_kv("distdir", stringify(_imp->params.distdir));
+ config_info->add_kv("pkgdir", stringify(_imp->params.pkgdir));
+ config_info->add_kv("securitydir", stringify(_imp->params.securitydir));
+ config_info->add_kv("setsdir", stringify(_imp->params.setsdir));
+ config_info->add_kv("newsdir", stringify(_imp->params.newsdir));
+ config_info->add_kv("format", _imp->params.entry_format);
+ config_info->add_kv("root", stringify(_imp->params.root));
+ 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);
+}
+
+PortageRepository::~PortageRepository()
+{
+}
+
+bool
+PortageRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ Context context("When checking for category '" + stringify(c) +
+ "' in " + stringify(name()) + ":");
+
+ need_category_names();
+ return _imp->category_names.end() !=
+ _imp->category_names.find(c);
+}
+
+bool
+PortageRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) + "' in " +
+ stringify(name()) + ":");
+
+ need_category_names();
+
+ CategoryMap::iterator cat_iter(_imp->category_names.find(q.category));
+
+ if (_imp->category_names.end() == cat_iter)
+ return false;
+
+ if (cat_iter->second)
+ return _imp->package_names.find(q) !=
+ _imp->package_names.end();
+ else
+ {
+ if (_imp->package_names.find(q) !=
+ _imp->package_names.end())
+ return true;
+
+ FSEntry fs(_imp->params.location);
+ fs /= stringify(q.category);
+ fs /= stringify(q.package);
+ if (! fs.is_directory())
+ return false;
+ _imp->package_names.insert(std::make_pair(q, false));
+ return true;
+ }
+}
+
+namespace
+{
+ /**
+ * Filter QualifiedPackageName instances by category.
+ *
+ * \ingroup grpportagerepository
+ */
+ struct CategoryFilter :
+ std::unary_function<bool, QualifiedPackageName>
+ {
+ /// Our category.
+ CategoryNamePart category;
+
+ /// Constructor.
+ CategoryFilter(const CategoryNamePart & c) :
+ category(c)
+ {
+ }
+
+ /// Predicate.
+ bool operator() (const QualifiedPackageName & a) const
+ {
+ return a.category == category;
+ }
+ };
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+PortageRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+
+ need_category_names();
+
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ CategoryMap::const_iterator i(_imp->category_names.begin()),
+ i_end(_imp->category_names.end());
+ for ( ; i != i_end ; ++i)
+ result->insert(i->first);
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+PortageRepository::do_package_names(const CategoryNamePart & c) const
+{
+ /* this isn't particularly fast because it isn't called very often. avoid
+ * changing the data structures used to make this faster at the expense of
+ * slowing down single item queries. */
+
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ need_category_names();
+
+ if (_imp->category_names.end() == _imp->category_names.find(c))
+ return std::tr1::shared_ptr<QualifiedPackageNameCollection>(new QualifiedPackageNameCollection::Concrete);
+
+ if ((_imp->params.location / stringify(c)).is_directory())
+ for (DirIterator d(_imp->params.location / stringify(c)), d_end ; d != d_end ; ++d)
+ {
+ if (! d->is_directory())
+ continue;
+ if (DirIterator() == std::find_if(DirIterator(*d), DirIterator(),
+ IsFileWithExtension(_imp->entries_ptr->file_extension())))
+ continue;
+
+ try
+ {
+ _imp->package_names.insert(std::make_pair(c + PackageNamePart(d->basename()), false));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping entry '" +
+ d->basename() + "' in category '" + stringify(c) + "' in repository '"
+ + stringify(name()) + "' (" + e.message() + ")");
+ }
+ }
+
+ _imp->category_names[c] = true;
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+
+ std::copy(_imp->package_names.begin(), _imp->package_names.end(),
+ transform_inserter(filter_inserter(result->inserter(), CategoryFilter(c)),
+ SelectFirst<const QualifiedPackageName, bool>()));
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+PortageRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ if (has_package_named(n))
+ {
+ need_version_names(n);
+ return _imp->version_specs.find(n)->second;
+ }
+ else
+ return std::tr1::shared_ptr<VersionSpecCollection>(new VersionSpecCollection::Concrete);
+}
+
+bool
+PortageRepository::do_has_version(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When checking for version '" + stringify(v) + "' in '"
+ + stringify(q) + "' in " + stringify(name()) + ":");
+
+ if (has_package_named(q))
+ {
+ need_version_names(q);
+ std::tr1::shared_ptr<VersionSpecCollection> vv(_imp->version_specs.find(q)->second);
+ return vv->end() != vv->find(v);
+ }
+ else
+ return false;
+}
+
+void
+PortageRepository::need_category_names() const
+{
+ if (_imp->has_category_names)
+ return;
+
+ Context context("When loading category names for " + stringify(name()) + ":");
+
+ Log::get_instance()->message(ll_debug, lc_context, "need_category_names");
+
+ if (! (_imp->params.location / "profiles" / "categories").exists())
+ {
+ Log::get_instance()->message(ll_qa, lc_context, "No categories file for repository at '"
+ + stringify(_imp->params.location) + "', faking it");
+ for (DirIterator d(_imp->params.location), d_end ; d != d_end ; ++d)
+ {
+ if (! d->is_directory())
+ continue;
+
+ std::string n(d->basename());
+ if (n == "CVS" || n == "distfiles" || n == "scripts" || n == "eclass" || n == "licences"
+ || n == "packages")
+ continue;
+
+ try
+ {
+ _imp->category_names.insert(std::make_pair(CategoryNamePart(n), false));
+ }
+ catch (const NameError &)
+ {
+ }
+ }
+ }
+ else
+ {
+ LineConfigFile cats(_imp->params.location / "profiles" / "categories");
+
+ for (LineConfigFile::Iterator line(cats.begin()), line_end(cats.end()) ;
+ line != line_end ; ++line)
+ _imp->category_names.insert(std::make_pair(CategoryNamePart(*line), false));
+ }
+
+ _imp->has_category_names = true;
+}
+
+void
+PortageRepository::need_version_names(const QualifiedPackageName & n) const
+{
+ if (_imp->package_names[n])
+ return;
+
+ Context context("When loading versions for '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ Log::get_instance()->message(ll_debug, lc_context, "need_version_names '" + stringify(n) + "'");
+
+ std::tr1::shared_ptr<VersionSpecCollection> v(new VersionSpecCollection::Concrete);
+
+ FSEntry path(_imp->params.location / stringify(n.category) /
+ stringify(n.package));
+
+ for (DirIterator e(path), e_end ; e != e_end ; ++e)
+ {
+ if (! IsFileWithExtension(stringify(n.package) + "-",
+ _imp->entries_ptr->file_extension())(*e))
+ continue;
+
+ try
+ {
+ v->insert(VersionSpec(strip_leading_string(
+ strip_trailing_string(e->basename(), _imp->entries_ptr->file_extension()),
+ stringify(n.package) + "-")));
+ }
+ catch (const NameError &)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping entry '"
+ + stringify(*e) + "' for '" + stringify(n) + "' in repository '"
+ + stringify(name()) + "'");
+ }
+ }
+
+ _imp->version_specs.insert(std::make_pair(n, v));
+ _imp->package_names[n] = true;
+}
+
+RepositoryName
+PortageRepository::fetch_repo_name(const std::string & location)
+{
+ try
+ {
+ do
+ {
+ FSEntry name_file(location);
+ name_file /= "profiles";
+ name_file /= "repo_name";
+
+ if (! name_file.is_regular_file())
+ break;
+
+ LineConfigFile f(name_file);
+ if (f.begin() == f.end())
+ break;
+ return RepositoryName(*f.begin());
+
+ } while (false);
+ }
+ catch (...)
+ {
+ }
+ Log::get_instance()->message(ll_qa, lc_no_context, "Couldn't open repo_name file in '"
+ + location + "/profiles/', falling back to a generated name (ignore this message if "
+ "you have yet to sync this repository).");
+
+ std::string modified_location(FSEntry(location).basename());
+ std::replace(modified_location.begin(), modified_location.end(), '/', '-');
+ return RepositoryName("x-" + modified_location);
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+PortageRepository::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (_imp->metadata.end() != _imp->metadata.find(
+ std::make_pair(q, v)))
+ return _imp->metadata.find(std::make_pair(q, v))->second;
+
+ Context context("When fetching metadata for '" + stringify(q) +
+ "-" + stringify(v) + "':");
+
+ if (! has_version(q, v))
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ std::tr1::shared_ptr<VersionMetadata> result(_imp->entries_ptr->generate_version_metadata(q, v));
+ _imp->metadata.insert(std::make_pair(std::make_pair(q, v), result));
+ return result;
+}
+
+bool
+PortageRepository::do_query_repository_masks(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! _imp->has_repo_mask)
+ {
+ Context context("When querying repository mask for '" + stringify(q) + "-"
+ + stringify(v) + "':");
+
+ FSEntry fff(_imp->params.location / "profiles" / "package.mask");
+ if (fff.exists())
+ {
+ LineConfigFile ff(fff);
+ for (LineConfigFile::Iterator line(ff.begin()), line_end(ff.end()) ;
+ line != line_end ; ++line)
+ {
+ std::tr1::shared_ptr<const PackageDepAtom> a(new PackageDepAtom(*line));
+ _imp->repo_mask[a->package()].push_back(a);
+ }
+ }
+
+ _imp->has_repo_mask = true;
+ }
+
+ RepositoryMaskMap::iterator r(_imp->repo_mask.find(q));
+ if (_imp->repo_mask.end() == r)
+ return false;
+ else
+ for (IndirectIterator<std::list<std::tr1::shared_ptr<const PackageDepAtom> >::const_iterator, const PackageDepAtom>
+ k(r->second.begin()), k_end(r->second.end()) ; k != k_end ; ++k)
+ if (match_package(*_imp->params.environment, *k, PackageDatabaseEntry(q, v, name())))
+ return true;
+
+ return false;
+}
+
+bool
+PortageRepository::do_query_profile_masks(const QualifiedPackageName & n,
+ const VersionSpec & v) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->profile_masked(n, v, name());
+}
+
+UseFlagState
+PortageRepository::do_query_use(const UseFlagName & f, const PackageDatabaseEntry * e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_state_ignoring_masks(f, e);
+}
+
+bool
+PortageRepository::do_query_use_mask(const UseFlagName & u, const PackageDatabaseEntry * e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_masked(u, e) ||
+ (arch_flags()->end() != arch_flags()->find(u) && use_enabled != do_query_use(u, e));
+}
+
+bool
+PortageRepository::do_query_use_force(const UseFlagName & u, const PackageDatabaseEntry * e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_forced(u, e);
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_arch_flags() const
+{
+ if (! _imp->arch_flags)
+ {
+ Context context("When loading arch list:");
+ _imp->arch_flags.reset(new UseFlagNameCollection::Concrete);
+
+ FSEntry a(_imp->params.location / "profiles" / "arch.list");
+ if (a.exists())
+ {
+ LineConfigFile archs(a);
+ std::copy(archs.begin(), archs.end(), create_inserter<UseFlagName>(_imp->arch_flags->inserter()));
+ }
+ else
+ {
+ Log::get_instance()->message(ll_qa, lc_no_context, "Couldn't open arch.list file in '"
+ + stringify(a) + "', arch flags may incorrectly show up as unmasked");
+ }
+ }
+
+ return _imp->arch_flags;
+}
+
+bool
+PortageRepository::do_is_licence(const std::string & s) const
+{
+ FSEntry l(_imp->params.location);
+ l /= "licenses";
+
+ if (! l.is_directory())
+ return false;
+
+ l /= s;
+ return l.exists() && l.is_regular_file();
+}
+
+void
+PortageRepository::need_mirrors() const
+{
+ if (! _imp->has_mirrors)
+ {
+ if ((_imp->params.location / "profiles" / "thirdpartymirrors").exists())
+ {
+ LineConfigFile mirrors(_imp->params.location / "profiles" / "thirdpartymirrors");
+ for (LineConfigFile::Iterator line(mirrors.begin()) ; line != mirrors.end() ; ++line)
+ {
+ std::vector<std::string> entries;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(entries));
+ if (! entries.empty())
+ {
+ /* pick up to five random mirrors only */
+ static Random r;
+ std::random_shuffle(next(entries.begin()), entries.end(), r);
+ if (entries.size() > 6)
+ entries.resize(6);
+ for (std::vector<std::string>::const_iterator e(next(entries.begin())),
+ e_end(entries.end()) ; e != e_end ; ++e)
+ _imp->mirrors.insert(std::make_pair(entries.at(0), *e));
+ }
+ }
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "No thirdpartymirrors file found in '"
+ + stringify(_imp->params.location / "profiles") + "', so mirror:// SRC_URI "
+ "components cannot be fetched");
+
+ _imp->has_mirrors = true;
+ }
+}
+
+void
+PortageRepository::do_install(const QualifiedPackageName & q, const VersionSpec & v,
+ const InstallOptions & o) const
+{
+ _imp->need_profiles();
+
+ if (! _imp->params.root.is_directory())
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since root ('" + stringify(_imp->params.root) + "') isn't a directory");
+
+ _imp->entries_ptr->install(q, v, o, _imp->profile_ptr);
+}
+
+std::tr1::shared_ptr<DepAtom>
+PortageRepository::do_package_set(const SetName & s) const
+{
+ if (s.data() == "system")
+ {
+ _imp->need_profiles();
+ return _imp->profile_ptr->system_packages();
+ }
+
+ return _imp->sets_ptr->package_set(s);
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+PortageRepository::sets_list() const
+{
+ return _imp->sets_ptr->sets_list();
+}
+
+bool
+PortageRepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+
+ if (_imp->params.sync.empty())
+ return false;
+
+ std::list<std::string> sync_list;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->params.sync, std::back_inserter(sync_list));
+
+ bool ok(false);
+ for (std::list<std::string>::const_iterator s(sync_list.begin()),
+ s_end(sync_list.end()) ; s != s_end ; ++s)
+ {
+ DefaultSyncer syncer(SyncerParams::create()
+ .environment(_imp->params.environment)
+ .local(stringify(_imp->params.location))
+ .remote(*s));
+ SyncOptions opts(_imp->params.sync_options);
+ try
+ {
+ syncer.sync(opts);
+ }
+ catch (const SyncFailedError & e)
+ {
+ continue;
+ }
+
+ ok=true;
+ break;
+ }
+
+ if (! ok)
+ throw SyncFailedError(stringify(_imp->params.location), _imp->params.sync);
+
+ return true;
+}
+
+void
+PortageRepository::invalidate()
+{
+ _imp.reset(new Implementation<PortageRepository>(this, _imp->params));
+}
+
+void
+PortageRepository::update_news() const
+{
+ _imp->news_ptr->update_news();
+}
+
+std::string
+PortageRepository::get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const
+{
+ Context context("When fetching environment variable '" + var + "' from repository '"
+ + stringify(name()) + "':");
+
+ _imp->need_profiles();
+
+ return _imp->entries_ptr->get_environment_variable(for_package.name,
+ for_package.version, var, _imp->profile_ptr);
+}
+
+std::tr1::shared_ptr<const RepositoryInfo>
+PortageRepository::info(bool verbose) const
+{
+ std::tr1::shared_ptr<const RepositoryInfo> result_non_verbose(Repository::info(verbose));
+ if (! verbose)
+ return result_non_verbose;
+
+ std::tr1::shared_ptr<RepositoryInfo> result(new RepositoryInfo);
+
+ for (RepositoryInfo::SectionIterator s(result_non_verbose->begin_sections()),
+ s_end(result_non_verbose->end_sections()) ; s != s_end ; ++s)
+ result->add_section(*s);
+
+ std::set<std::string> info_pkgs;
+ if ((_imp->params.location / "profiles" / "info_pkgs").exists())
+ {
+ LineConfigFile vars(_imp->params.location / "profiles" / "info_pkgs");
+ info_pkgs.insert(vars.begin(), vars.end());
+ }
+
+ if (! info_pkgs.empty())
+ {
+ std::tr1::shared_ptr<RepositoryInfoSection> package_info(new RepositoryInfoSection("Package information"));
+ for (std::set<std::string>::const_iterator i(info_pkgs.begin()),
+ i_end(info_pkgs.end()) ; i != i_end ; ++i)
+ {
+ std::tr1::shared_ptr<const PackageDatabaseEntryCollection> q(
+ _imp->params.environment->package_database()->query(PackageDepAtom(*i), is_installed_only,
+ qo_order_by_version));
+ if (q->empty())
+ package_info->add_kv(*i, "(none)");
+ else
+ {
+ std::set<VersionSpec> versions;
+
+ /* don't use std::transform, it breaks g++4.1 */
+ // std::transform(q->begin(), q->end(), std::inserter(versions, versions.end()),
+ // std::mem_fun_ref(&PackageDatabaseEntry::get<pde_version>));
+ for (PackageDatabaseEntryCollection::Iterator qq(q->begin()), qq_end(q->end()) ;
+ qq != qq_end ; ++qq)
+ versions.insert(qq->version);
+ package_info->add_kv(*i, join(versions.begin(), versions.end(), ", "));
+ }
+ }
+
+ result->add_section(package_info);
+ }
+
+ std::set<std::string> info_vars;
+ if ((_imp->params.location / "profiles" / "info_vars").exists())
+ {
+ LineConfigFile vars(_imp->params.location / "profiles" / "info_vars");
+ info_vars.insert(vars.begin(), vars.end());
+ }
+
+ if (! info_vars.empty() && ! info_pkgs.empty() &&
+ ! version_specs(QualifiedPackageName(*info_pkgs.begin()))->empty())
+ {
+ PackageDatabaseEntry e(QualifiedPackageName(*info_pkgs.begin()),
+ *version_specs(QualifiedPackageName(*info_pkgs.begin()))->last(),
+ name());
+ std::tr1::shared_ptr<RepositoryInfoSection> variable_info(new RepositoryInfoSection("Variable information"));
+ for (std::set<std::string>::const_iterator i(info_vars.begin()),
+ i_end(info_vars.end()) ; i != i_end ; ++i)
+ variable_info->add_kv(*i, get_environment_variable(e, *i));
+
+ result->add_section(variable_info);
+ }
+ else if (! info_vars.empty())
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Skipping info_vars for '" + stringify(name()) +
+ "' because info_pkgs is not usable");
+
+ return result;
+}
+
+std::string
+PortageRepository::profile_variable(const std::string & s) const
+{
+ _imp->need_profiles();
+
+ return _imp->profile_ptr->environment_variable(s);
+}
+
+PortageRepository::MirrorsIterator
+PortageRepository::begin_mirrors(const std::string & s) const
+{
+ need_mirrors();
+ return MirrorsIterator(_imp->mirrors.equal_range(s).first);
+}
+
+PortageRepository::MirrorsIterator
+PortageRepository::end_mirrors(const std::string & s) const
+{
+ need_mirrors();
+ return MirrorsIterator(_imp->mirrors.equal_range(s).second);
+}
+
+std::tr1::shared_ptr<const PortageRepository::VirtualsCollection>
+PortageRepository::virtual_packages() const
+{
+ Context context("When loading virtual packages for repository '" +
+ stringify(name()) + "'");
+
+ Log::get_instance()->message(ll_debug, lc_context, "Loading virtual packages for repository '"
+ + stringify(name()) + "'");
+
+ _imp->need_profiles();
+ need_category_names();
+
+ std::tr1::shared_ptr<VirtualsCollection> result(new VirtualsCollection::Concrete);
+
+ for (PortageRepositoryProfile::VirtualsIterator i(_imp->profile_ptr->begin_virtuals()),
+ i_end(_imp->profile_ptr->end_virtuals()) ; i != i_end ; ++i)
+ result->insert(RepositoryVirtualsEntry::create()
+ .provided_by_atom(i->second)
+ .virtual_name(i->first));
+
+ Log::get_instance()->message(ll_debug, lc_context, "Loaded " + stringify(result->size()) +
+ " virtual packages for repository '" + stringify(name()) + "'");
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+PortageRepository::virtual_package_version_metadata(const RepositoryVirtualsEntry & p,
+ const VersionSpec & v) const
+{
+ std::tr1::shared_ptr<const VersionMetadata> m(version_metadata(p.provided_by_atom->package(), v));
+ std::tr1::shared_ptr<PortageVirtualVersionMetadata> result(new PortageVirtualVersionMetadata(
+ m->slot, PackageDatabaseEntry(p.provided_by_atom->package(), v, name())));
+
+ result->eapi = m->eapi;
+ result->build_depend_string = "=" + stringify(p.provided_by_atom->package()) + "-" + stringify(v);
+ result->run_depend_string = "=" + stringify(p.provided_by_atom->package()) + "-" + stringify(v);
+
+ return result;
+
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_use_expand_flags() const
+{
+ _imp->need_profiles();
+
+ std::tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand()),
+ i_end(_imp->profile_ptr->end_use_expand()) ; i != i_end ; ++i)
+ {
+ std::list<std::string> values;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->profile_ptr->environment_variable(
+ stringify(*i)), std::back_inserter(values));
+ for (std::list<std::string>::const_iterator j(values.begin()), j_end(values.end()) ;
+ j != j_end ; ++j)
+ {
+ std::string f(stringify(*i) + "_" + *j), lower_f;
+ std::transform(f.begin(), f.end(), std::back_inserter(lower_f), &::tolower);
+ result->insert(UseFlagName(lower_f));
+ }
+ }
+
+ return result;
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_use_expand_prefixes() const
+{
+ _imp->need_profiles();
+
+ std::tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand()),
+ i_end(_imp->profile_ptr->end_use_expand()) ; i != i_end ; ++i)
+ {
+ std::string lower_i;
+ std::transform(i->data().begin(), i->data().end(), std::back_inserter(lower_i), &::tolower);
+ result->insert(UseFlagName(lower_i));
+ }
+
+ return result;
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_use_expand_hidden_prefixes() const
+{
+ _imp->need_profiles();
+
+ std::tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand_hidden()),
+ i_end(_imp->profile_ptr->end_use_expand_hidden()) ; i != i_end ; ++i)
+ {
+ std::string lower_i;
+ std::transform(i->data().begin(), i->data().end(), std::back_inserter(lower_i), &::tolower);
+ result->insert(UseFlagName(lower_i));
+ }
+
+ return result;
+}
+
+UseFlagName
+PortageRepository::do_use_expand_name(const UseFlagName & u) const
+{
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand()),
+ i_end(_imp->profile_ptr->end_use_expand()) ; i != i_end ; ++i)
+ {
+ std::string lower_i;
+ std::transform(i->data().begin(), i->data().end(), std::back_inserter(lower_i), ::tolower);
+ if (0 == lower_i.compare(0, lower_i.length(), stringify(u), 0, lower_i.length()))
+ return *i;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Not a use expand name: '" + stringify(u) + "'");
+}
+
+UseFlagName
+PortageRepository::do_use_expand_value(const UseFlagName & u) const
+{
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand()),
+ i_end(_imp->profile_ptr->end_use_expand()) ; i != i_end ; ++i)
+ {
+ std::string lower_i;
+ std::transform(i->data().begin(), i->data().end(), std::back_inserter(lower_i), ::tolower);
+ if (0 == lower_i.compare(0, lower_i.length(), stringify(u), 0, lower_i.length()))
+ return UseFlagName(stringify(u).substr(lower_i.length() + 1));
+ }
+
+ throw InternalError(PALUDIS_HERE, "Not a use expand name: '" + stringify(u) + "'");
+}
+
+void
+PortageRepository::regenerate_cache() const
+{
+ _imp->names_cache->regenerate_cache();
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+PortageRepository::do_category_names_containing_package(const PackageNamePart & p) const
+{
+ if (! _imp->names_cache->usable())
+ return Repository::do_category_names_containing_package(p);
+
+ std::tr1::shared_ptr<const CategoryNamePartCollection> result(
+ _imp->names_cache->category_names_containing_package(p));
+
+ return result ? result : Repository::do_category_names_containing_package(p);
+}
+
+PortageRepository::ProfilesIterator
+PortageRepository::begin_profiles() const
+{
+ _imp->need_profiles_desc();
+ return ProfilesIterator(_imp->profiles_desc.begin());
+}
+
+PortageRepository::ProfilesIterator
+PortageRepository::end_profiles() const
+{
+ _imp->need_profiles_desc();
+ return ProfilesIterator(_imp->profiles_desc.end());
+}
+
+PortageRepository::ProfilesIterator
+PortageRepository::find_profile(const FSEntry & location) const
+{
+ _imp->need_profiles_desc();
+ for (ProfilesDesc::const_iterator i(_imp->profiles_desc.begin()),
+ i_end(_imp->profiles_desc.end()) ; i != i_end ; ++i)
+ if (i->path == location)
+ return ProfilesIterator(i);
+ return ProfilesIterator(_imp->profiles_desc.end());
+}
+
+void
+PortageRepository::set_profile(const ProfilesIterator & iter)
+{
+ Context context("When setting profile by iterator:");
+
+ _imp->profile_ptr = iter->profile;
+
+ try
+ {
+ _imp->params.environment->package_database()->fetch_repository(
+ RepositoryName("virtuals"))->invalidate();
+ }
+ catch (const NoSuchRepositoryError &)
+ {
+ }
+}
+
+void
+PortageRepository::set_profile_by_arch(const UseFlagName & arch)
+{
+ Context context("When setting profile by arch '" + stringify(arch) + "':");
+
+ for (ProfilesIterator p(begin_profiles()), p_end(end_profiles()) ; p != p_end ; ++p)
+ if (p->arch == stringify(arch) && p->status == "stable")
+ {
+ set_profile(p);
+ return;
+ }
+
+ for (ProfilesIterator p(begin_profiles()), p_end(end_profiles()) ; p != p_end ; ++p)
+ if (p->arch == stringify(arch))
+ {
+ set_profile(p);
+ return;
+ }
+
+ throw ConfigurationError("Cannot find a profile appropriate for '" + stringify(arch) + "'");
+}
+
+std::string
+PortageRepository::do_describe_use_flag(const UseFlagName & f,
+ const PackageDatabaseEntry * const e) const
+{
+ if (! _imp->use_desc)
+ _imp->use_desc.reset(new UseDesc(_imp->params.location / "profiles"));
+
+ return _imp->use_desc->describe(f, e);
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository.hh b/0.18.0/paludis/repositories/portage/portage_repository.hh
new file mode 100644
index 000000000..e6326a0a9
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository.hh
@@ -0,0 +1,187 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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_PORTAGE_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_PORTAGE_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/repositories/portage/portage_repository_params.hh>
+#include <paludis/repositories/portage/portage_repository_profile.hh>
+#include <string>
+
+/** \file
+ * Declaration for the PortageRepository class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class PortageRepositoryProfile;
+ class PortageRepositoryNews;
+
+#include <paludis/repositories/portage/portage_repository-sr.hh>
+
+ /**
+ * A PortageRepository is a Repository that handles the layout used by
+ * Portage for the main Gentoo tree.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE PortageRepository :
+ public Repository,
+ public RepositoryMaskInterface,
+ public RepositoryUseInterface,
+ public RepositoryInstallableInterface,
+ public RepositorySyncableInterface,
+ public RepositoryNewsInterface,
+ public RepositorySetsInterface,
+ public RepositoryEnvironmentVariableInterface,
+ public RepositoryMirrorsInterface,
+ public RepositoryVirtualsInterface,
+ private PrivateImplementationPattern<PortageRepository>
+ {
+ private:
+ void need_category_names() const;
+ void need_version_names(const QualifiedPackageName &) const;
+ void need_mirrors() const;
+ PackageDatabaseEntryCollection::Iterator find_best(PackageDatabaseEntryCollection & c,
+ const PackageDatabaseEntry & e) const;
+
+ protected:
+ /**
+ * Try to get the repository name for a particular repository.
+ */
+ static RepositoryName fetch_repo_name(const std::string & location);
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names_containing_package(
+ const PackageNamePart & p) const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_query_repository_masks(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_query_profile_masks(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual std::tr1::shared_ptr<DepAtom> do_package_set(const SetName &) const;
+
+ virtual std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+
+ virtual bool do_sync() const;
+
+ virtual std::tr1::shared_ptr<const VirtualsCollection> virtual_packages() const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> virtual_package_version_metadata(
+ const RepositoryVirtualsEntry &, const VersionSpec & v) const;
+
+ /* RepositoryUseInterface */
+
+ virtual UseFlagState do_query_use(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual bool do_query_use_mask(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual bool do_query_use_force(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_arch_flags() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_flags() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_hidden_prefixes() const;
+ virtual UseFlagName do_use_expand_name(const UseFlagName & u) const;
+ virtual UseFlagName do_use_expand_value(const UseFlagName & u) const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_prefixes() const;
+ virtual std::string do_describe_use_flag(const UseFlagName &,
+ const PackageDatabaseEntry * const) const;
+
+ /* end of RepositoryUseInterface */
+
+ public:
+ virtual std::tr1::shared_ptr<const RepositoryInfo> info(bool verbose) const;
+
+ /**
+ * Constructor.
+ */
+ PortageRepository(const PortageRepositoryParams &);
+
+ /**
+ * Destructor.
+ */
+ ~PortageRepository();
+
+ virtual void invalidate();
+ virtual void regenerate_cache() const;
+
+ virtual void update_news() const;
+
+ virtual std::string get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const;
+
+ virtual MirrorsIterator begin_mirrors(const std::string & s) const;
+ virtual MirrorsIterator end_mirrors(const std::string & s) const;
+
+ ///\name Information about PortageRepository
+ ///\{
+
+ std::string profile_variable(const std::string &) const;
+
+ typedef libwrapiter::ForwardIterator<PortageRepository, std::pair<
+ const QualifiedPackageName, std::tr1::shared_ptr<const PackageDepAtom> > > OurVirtualsIterator;
+
+ ///\}
+
+ ///\name Profile setting and querying functions
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<PortageRepository,
+ const PortageRepositoryProfilesDescLine> ProfilesIterator;
+ ProfilesIterator begin_profiles() const;
+ ProfilesIterator end_profiles() const;
+
+ ProfilesIterator find_profile(const FSEntry & location) const;
+ void set_profile(const ProfilesIterator & iter);
+ void set_profile_by_arch(const UseFlagName &);
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository.sr b/0.18.0/paludis/repositories/portage/portage_repository.sr
new file mode 100644
index 000000000..5f4c5156c
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository.sr
@@ -0,0 +1,10 @@
+make_class_PortageRepositoryProfilesDescLine()
+{
+ key path FSEntry
+ key arch std::string
+ key status std::string
+ key profile "std::tr1::shared_ptr<PortageRepositoryProfile>"
+ allow_named_args
+}
+
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_TEST.cc b/0.18.0/paludis/repositories/portage/portage_repository_TEST.cc
new file mode 100644
index 000000000..df1589272
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_TEST.cc
@@ -0,0 +1,665 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/portage/portage_repository.hh>
+#include <paludis/repositories/portage/make_ebuild_repository.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/environment/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+/** \file
+ * Test cases for PortageRepository.
+ *
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test PortageRepository repository names.
+ *
+ */
+ struct PortageRepositoryRepoNameTest : TestCase
+ {
+ PortageRepositoryRepoNameTest() : TestCase("repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo1");
+ keys->insert("profile", "portage_repository_TEST_dir/repo1/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "test-repo-1");
+ }
+ } test_portage_repository_repo_name;
+
+ /**
+ * \test Test PortageRepository repository with no names.
+ *
+ */
+ struct PortageRepositoryNoRepoNameTest : TestCase
+ {
+ PortageRepositoryNoRepoNameTest() : TestCase("no repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo2");
+ keys->insert("profile", "portage_repository_TEST_dir/repo2/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "x-repo2");
+ }
+ } test_portage_repository_no_repo_name;
+
+ /**
+ * \test Test PortageRepository repository empty names.
+ *
+ */
+ struct PortageRepositoryEmptyRepoNameTest : TestCase
+ {
+ PortageRepositoryEmptyRepoNameTest() : TestCase("empty repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo3");
+ keys->insert("profile", "portage_repository_TEST_dir/repo3/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "x-repo3");
+ }
+ } test_portage_repository_empty_repo_name;
+
+ /**
+ * \test Test PortageRepository repository has_category_named.
+ *
+ */
+ struct PortageRepositoryHasCategoryNamedTest : TestCase
+ {
+ PortageRepositoryHasCategoryNamedTest() : TestCase("has category named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo1");
+ keys->insert("profile", "portage_repository_TEST_dir/repo1/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-one")));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-two")));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-three")));
+ TEST_CHECK(! repo->has_category_named(CategoryNamePart("cat-four")));
+ }
+ }
+ } test_portage_repository_has_category_named;
+
+ /**
+ * \test Test PortageRepository category_names.
+ *
+ */
+ struct PortageRepositoryCategoryNamesTest : TestCase
+ {
+ PortageRepositoryCategoryNamesTest() : TestCase("category names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo1");
+ keys->insert("profile", "portage_repository_TEST_dir/repo1/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ std::tr1::shared_ptr<const CategoryNamePartCollection> c(repo->category_names());
+ TEST_CHECK(c->end() != c->find(CategoryNamePart("cat-one")));
+ TEST_CHECK(c->end() != c->find(CategoryNamePart("cat-two")));
+ TEST_CHECK(c->end() != c->find(CategoryNamePart("cat-three")));
+ TEST_CHECK(c->end() == c->find(CategoryNamePart("cat-four")));
+ TEST_CHECK_EQUAL(3, std::distance(c->begin(), c->end()));
+ }
+ }
+ } test_portage_repository_category_names;
+
+ /**
+ * \test Test PortageRepository has_package_named.
+ *
+ */
+ struct PortageRepositoryHasPackageNamedTest : TestCase
+ {
+ PortageRepositoryHasPackageNamedTest() : TestCase("has package named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-both")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-one")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-neither")));
+ }
+ }
+ } test_portage_repository_has_package_named;
+
+ /**
+ * \test Test PortageRepository has_package_named cached.
+ *
+ */
+ struct PortageRepositoryHasPackageNamedCachedTest : TestCase
+ {
+ PortageRepositoryHasPackageNamedCachedTest() : TestCase("has package named cached") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ repo->package_names(CategoryNamePart("cat-one"));
+ repo->package_names(CategoryNamePart("cat-two"));
+ repo->package_names(CategoryNamePart("cat-three"));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-both")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-one")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-neither")));
+ }
+ }
+ } test_portage_repository_has_package_named_cached;
+
+ /**
+ * \test Test PortageRepository package_names.
+ *
+ */
+ struct PortageRepositoryPackageNamesTest : TestCase
+ {
+ PortageRepositoryPackageNamesTest() : TestCase("package names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> names;
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ names = repo->package_names(CategoryNamePart("cat-one"));
+ TEST_CHECK(! names->empty());
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-one/pkg-both")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-one/pkg-two")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-one/pkg-neither")));
+ TEST_CHECK_EQUAL(2, std::distance(names->begin(), names->end()));
+
+ names = repo->package_names(CategoryNamePart("cat-two"));
+ TEST_CHECK(! names->empty());
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-two/pkg-one")));
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-two/pkg-both")));
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-two/pkg-two")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-two/pkg-neither")));
+ TEST_CHECK_EQUAL(2, std::distance(names->begin(), names->end()));
+
+ names = repo->package_names(CategoryNamePart("cat-three"));
+ TEST_CHECK(names->empty());
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-one")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-both")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-two")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-neither")));
+ TEST_CHECK_EQUAL(0, std::distance(names->begin(), names->end()));
+ }
+ }
+ } test_portage_repository_package_names;
+
+ /**
+ * \test Test PortageRepository bad package names.
+ *
+ */
+ struct PortageRepositoryBadPackageNamesTest : TestCase
+ {
+ PortageRepositoryBadPackageNamesTest() : TestCase("bad package names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo5");
+ keys->insert("profile", "portage_repository_TEST_dir/repo5/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ std::tr1::shared_ptr<const QualifiedPackageNameCollection> names;
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ names = repo->package_names(CategoryNamePart("cat-one"));
+ TEST_CHECK(! names->empty());
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK_EQUAL(1, std::distance(names->begin(), names->end()));
+ }
+ }
+ } test_portage_repository_bad_package_names;
+
+ /**
+ * \test Test PortageRepository has_version.
+ *
+ */
+ struct PortageRepositoryHasVersionTest : TestCase
+ {
+ PortageRepositoryHasVersionTest() : TestCase("has version") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_version(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("1")));
+ TEST_CHECK(repo->has_version(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("1.1-r1")));
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("2")));
+
+ TEST_CHECK(repo->has_version(QualifiedPackageName("cat-one/pkg-both"), VersionSpec("3.45")));
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-one/pkg-both"), VersionSpec("1")));
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-one/pkg-both"), VersionSpec("1.23")));
+
+ TEST_CHECK(repo->has_version(QualifiedPackageName("cat-two/pkg-two"), VersionSpec("2")));
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-two/pkg-two"), VersionSpec("1")));
+
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-two/pkg-both"), VersionSpec("3.45")));
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-two/pkg-both"), VersionSpec("1")));
+ TEST_CHECK(repo->has_version(QualifiedPackageName("cat-two/pkg-both"), VersionSpec("1.23")));
+
+ TEST_CHECK(! repo->has_version(QualifiedPackageName("cat-two/pkg-neither"), VersionSpec("1")));
+ }
+ }
+ } test_portage_repository_has_version;
+
+ /**
+ * \test Test PortageRepository versions.
+ *
+ */
+ struct PortageRepositoryVersionsTest : TestCase
+ {
+ PortageRepositoryVersionsTest() : TestCase("versions") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ std::tr1::shared_ptr<const VersionSpecCollection> versions;
+
+ versions = repo->version_specs(QualifiedPackageName("cat-one/pkg-one"));
+ TEST_CHECK(! versions->empty());
+ TEST_CHECK_EQUAL(2, std::distance(versions->begin(), versions->end()));
+ TEST_CHECK(versions->end() != versions->find(VersionSpec("1")));
+ TEST_CHECK(versions->end() != versions->find(VersionSpec("1.1-r1")));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("2")));
+
+ versions = repo->version_specs(QualifiedPackageName("cat-one/pkg-neither"));
+ TEST_CHECK(versions->empty());
+ TEST_CHECK_EQUAL(0, std::distance(versions->begin(), versions->end()));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("1")));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("1.1-r1")));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("2")));
+ }
+ }
+ } test_portage_repository_versions;
+
+ /**
+ * \test Test PortageRepository duff versions.
+ *
+ */
+ struct PortageRepositoryDuffVersionsTest : TestCase
+ {
+ PortageRepositoryDuffVersionsTest() : TestCase("duff versions") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo8");
+ keys->insert("profile", "portage_repository_TEST_dir/repo8/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ std::tr1::shared_ptr<const VersionSpecCollection> versions;
+
+ versions = repo->version_specs(QualifiedPackageName("cat-one/pkg-one"));
+ TEST_CHECK(! versions->empty());
+ TEST_CHECK_EQUAL(2, std::distance(versions->begin(), versions->end()));
+ TEST_CHECK(versions->end() != versions->find(VersionSpec("1")));
+ TEST_CHECK(versions->end() != versions->find(VersionSpec("1.1-r1")));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("2")));
+
+ versions = repo->version_specs(QualifiedPackageName("cat-one/pkg-neither"));
+ TEST_CHECK(versions->empty());
+ TEST_CHECK_EQUAL(0, std::distance(versions->begin(), versions->end()));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("1")));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("1.1-r1")));
+ TEST_CHECK(versions->end() == versions->find(VersionSpec("2")));
+ }
+ }
+ } test_portage_repository_duff_versions;
+
+ /**
+ * \test Test PortageRepository cached metadata.
+ *
+ */
+ struct PortageRepositoryMetadataCachedTest : TestCase
+ {
+ PortageRepositoryMetadataCachedTest() : TestCase("metadata cached") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo6");
+ keys->insert("profile", "portage_repository_TEST_dir/repo6/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ std::tr1::shared_ptr<const VersionMetadata> m;
+
+ m = repo->version_metadata(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("1"));
+ TEST_CHECK_EQUAL(m->description, "the-description");
+
+ TEST_CHECK_THROWS(repo->version_metadata(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("2")),
+ NoSuchPackageError);
+ TEST_CHECK_THROWS(repo->version_metadata(QualifiedPackageName("cat-two/pkg-one"), VersionSpec("1")),
+ NoSuchPackageError);
+ }
+ }
+ } test_portage_repository_metadata_cached;
+
+ /**
+ * \test Test PortageRepository uncached metadata.
+ *
+ */
+ struct PortageRepositoryMetadataUncachedTest : TestCase
+ {
+ PortageRepositoryMetadataUncachedTest() : TestCase("metadata uncached") { }
+
+ bool skip() const
+ {
+ return ! getenv_with_default("SANDBOX_ON", "").empty();
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo7");
+ keys->insert("profile", "portage_repository_TEST_dir/repo7/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ std::tr1::shared_ptr<const VersionMetadata> m;
+
+ m = repo->version_metadata(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("1"));
+ TEST_CHECK_EQUAL(m->description, "The Description");
+ TEST_CHECK_EQUAL(m->eapi, "0");
+ }
+ }
+ } test_portage_repository_metadata_uncached;
+
+ /**
+ * \test Test PortageRepository unparsable metadata.
+ *
+ */
+ struct PortageRepositoryMetadataUnparsableTest : TestCase
+ {
+ PortageRepositoryMetadataUnparsableTest() : TestCase("metadata unparsable") { }
+
+ bool skip() const
+ {
+ return ! getenv_with_default("SANDBOX_ON", "").empty();
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo7");
+ keys->insert("profile", "portage_repository_TEST_dir/repo7/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ std::tr1::shared_ptr<const VersionMetadata> m;
+
+ m = repo->version_metadata(QualifiedPackageName("cat-one/pkg-two"), VersionSpec("1"));
+ TEST_CHECK_EQUAL(m->eapi, "UNKNOWN");
+ }
+ }
+ } test_portage_repository_metadata_unparsable;
+
+ /**
+ * \test Test PortageRepository query_use and query_use_mask functions.
+ *
+ */
+ struct PortageRepositoryQueryUseTest : TestCase
+ {
+ PortageRepositoryQueryUseTest() : TestCase("USE query") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo9");
+ keys->insert("profile", "portage_repository_TEST_dir/repo9/profiles/profile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ PackageDatabaseEntry p1(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("1"),
+ RepositoryName("test-repo-9"));
+ PackageDatabaseEntry p2(QualifiedPackageName("cat-two/pkg-two"), VersionSpec("1"),
+ RepositoryName("test-repo-9"));
+ PackageDatabaseEntry p3(QualifiedPackageName("cat-one/pkg-none"), VersionSpec("1"),
+ RepositoryName("test-repo-9"));
+ PackageDatabaseEntry p4(QualifiedPackageName("cat-one/pkg-one"), VersionSpec("2"),
+ RepositoryName("test-repo-9"));
+
+ TEST_CHECK(repo->query_use(UseFlagName("flag1"), &p1) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag2"), &p1) == use_disabled);
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag2"), &p1));
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag2"), &p3));
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag3"), &p2));
+ TEST_CHECK(! repo->query_use_mask(UseFlagName("flag3"), &p1));
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag3"), &p4));
+ TEST_CHECK(repo->query_use(UseFlagName("flag3"), &p1) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag4"), &p3) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag5"), &p2) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag5"), &p1) == use_unspecified);
+ }
+ }
+ } test_portage_repository_query_use;
+
+ /**
+ * \test Test PortageRepository query_profile_masks functions.
+ *
+ */
+ struct PortageRepositoryQueryProfileMasksTest : TestCase
+ {
+ PortageRepositoryQueryProfileMasksTest() : TestCase("profiles package.mask") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "portage_repository_TEST_dir/repo10");
+ keys->insert("profiles", "portage_repository_TEST_dir/repo10/profiles/profile/subprofile");
+ std::tr1::shared_ptr<PortageRepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->query_profile_masks(QualifiedPackageName("cat/masked"),
+ VersionSpec("0")));
+ TEST_CHECK(! repo->query_profile_masks(QualifiedPackageName("cat/not_masked"),
+ VersionSpec("0")));
+ TEST_CHECK(! repo->query_profile_masks(QualifiedPackageName("cat/was_masked"),
+ VersionSpec("0")));
+ }
+ }
+ } test_portage_repository_query_profile_masks;
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh b/0.18.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..8c0b2902d
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d portage_repository_TEST_dir ] ; then
+ rm -fr portage_repository_TEST_dir
+else
+ true
+fi
+
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_TEST_setup.sh b/0.18.0/paludis/repositories/portage/portage_repository_TEST_setup.sh
new file mode 100755
index 000000000..5fc9373ba
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_TEST_setup.sh
@@ -0,0 +1,226 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir portage_repository_TEST_dir || exit 1
+cd portage_repository_TEST_dir || exit 1
+
+mkdir -p repo1/{eclass,distfiles,profiles/profile} || exit 1
+cd repo1 || exit 1
+echo "test-repo-1" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+cat-three
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cd ..
+
+mkdir -p repo2/{eclass,distfiles,profiles/profile} || exit 1
+cd repo2 || exit 1
+cat <<END > profiles/categories || exit 1
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cd ..
+
+
+mkdir -p repo3/{eclass,distfiles,profiles/profile} || exit 1
+cd repo3 || exit 1
+echo "# test-repo-3" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cd ..
+
+
+mkdir -p repo4/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo4/{cat-one/{pkg-one,pkg-both},cat-two/{pkg-two,pkg-both}} || exit 1
+cd repo4 || exit 1
+echo "test-repo-4" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.1-r1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-both/pkg-both-3.45.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-two/pkg-two-2.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-both/pkg-both-1.23.ebuild || exit 1
+END
+cd ..
+
+
+mkdir -p repo5/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo5/cat-one/{pkg-one,pkg-1,pkg.one} || exit 1
+cd repo5 || exit 1
+echo "test-repo-5" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-1/pkg-1-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg.one/pkg.one-1.ebuild || exit 1
+END
+cd ..
+
+
+mkdir -p repo6/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo6/cat-one/pkg-one || exit 1
+mkdir -p repo6/metadata/cache/cat-one
+cd repo6 || exit 1
+echo "test-repo-6" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > metadata/cache/cat-one/pkg-one-1
+the/depend
+the/rdepend
+the-slot
+the-src-uri
+the-restrict
+the-homepage
+the-license
+the-description
+the-keywords
+
+the-iuse
+unused
+the/pdepend
+the/provide
+0
+END
+cd ..
+
+
+mkdir -p repo7/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo7/cat-one/pkg-{one,two} || exit 1
+mkdir -p repo7/metadata/cache/cat-{one,two}
+cd repo7 || exit 1
+echo "test-repo-7" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+END
+cat <<END > cat-one/pkg-two/pkg-two-1.ebuild || exit 1
+i am a fish
+END
+cd ..
+
+
+mkdir -p repo8/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo8/{cat-one/{pkg-one,pkg-both},cat-two/{pkg-two,pkg-both}} || exit 1
+cd repo8 || exit 1
+echo "test-repo-8" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-1-monkey.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.1-r1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-both/pkg-both-3.45.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-both/pkg-both-3.45_r1.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-two/pkg-two-2.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-both/pkg-both-1.23.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-both/pkg-both-.ebuild || exit 1
+END
+cd ..
+
+
+mkdir -p repo9/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo9/{cat-one/pkg-one,cat-two/pkg-two} || exit 1
+cd repo9 || exit 1
+echo "test-repo-9" > profiles/repo_name || exit 1
+cat <<END >profiles/categories || exit 1
+cat-one
+cat-two
+END
+cat <<END >profiles/profile/make.defaults || exit 1
+ARCH=test
+USE="flag1 flag2 flag3 -flag4 -flag5"
+END
+cat <<END >profiles/profile/use.mask || exit 1
+flag2
+END
+cat <<END >profiles/profile/use.force || exit 1
+flag4
+END
+cat <<END >profiles/profile/package.use.mask || exit 1
+cat-two/pkg-two flag3
+>=cat-one/pkg-one-2 flag3
+END
+cat <<END >profiles/profile/package.use.force || exit 1
+cat-two/pkg-two flag5
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-2.ebuild || exit 1
+cat <<END > cat-two/pkg-two/pkg-two-1.ebuild || exit 1
+END
+cd ..
+
+mkdir -p repo10/{eclass,distfiles,profiles/profile/subprofile} || exit 1
+cd repo10 || exit 1
+echo "test-repo-10" > profiles/repo_name || exit 1
+cat <<END >profiles/profile/make.defaults || exit 1
+ARCH=test
+USE="flag1 flag2 flag3 -flag4 -flag5"
+END
+cat <<END >profiles/categories || exit 1
+cat
+END
+cat <<END >profiles/profile/package.mask
+cat/masked
+cat/was_masked
+END
+cat <<END >profiles/profile/subprofile/package.mask
+-cat/was_masked
+END
+cat <<END >profiles/profile/subprofile/parent
+..
+END
+cd ..
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_entries.cc b/0.18.0/paludis/repositories/portage/portage_repository_entries.cc
new file mode 100644
index 000000000..6abed92ba
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_entries.cc
@@ -0,0 +1,43 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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 "portage_repository_entries.hh"
+#include "ebuild_entries.hh"
+
+using namespace paludis;
+
+PortageRepositoryEntries::PortageRepositoryEntries(const std::string & ext) :
+ _ext(ext)
+{
+}
+
+PortageRepositoryEntries::~PortageRepositoryEntries()
+{
+}
+
+NoSuchPortageRepositoryEntriesType::NoSuchPortageRepositoryEntriesType(const std::string & format) throw ():
+ ConfigurationError("No available maker for Portage repository entries type '" + format + "'")
+{
+}
+
+PortageRepositoryEntriesMaker::PortageRepositoryEntriesMaker()
+{
+ register_maker("ebuild", &EbuildEntries::make_ebuild_entries);
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_entries.hh b/0.18.0/paludis/repositories/portage/portage_repository_entries.hh
new file mode 100644
index 000000000..2cee99324
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_entries.hh
@@ -0,0 +1,133 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_PORTAGE_REPOSITORY_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_METADATA_HH 1
+
+#include <paludis/name.hh>
+#include <paludis/repository.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/version_metadata.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/virtual_constructor.hh>
+#include <paludis/repositories/portage/portage_repository_profile.hh>
+#include <paludis/repositories/portage/portage_repository_params.hh>
+#include <string>
+
+/** \file
+ * Declaration for the PortageRepositoryEntries class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class PortageRepository;
+ class Environment;
+
+ /**
+ * Handle entries (for example, ebuilds) in a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE PortageRepositoryEntries
+ {
+ private:
+ const std::string _ext;
+
+ protected:
+ ///\name Basic operations
+ ///\{
+
+ /// Constructor, with our file extension
+ PortageRepositoryEntries(const std::string & ext);
+
+ ///\}
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ virtual ~PortageRepositoryEntries();
+
+ ///\}
+
+ /**
+ * Return our file extension, including the dot.
+ */
+ std::string file_extension() const
+ {
+ return _ext;
+ }
+
+ /**
+ * Generate version metadata.
+ */
+ virtual std::tr1::shared_ptr<VersionMetadata> generate_version_metadata(const QualifiedPackageName &,
+ const VersionSpec &) const = 0;
+
+ /**
+ * Fetch an environment variable.
+ */
+ virtual std::string get_environment_variable(const QualifiedPackageName &,
+ const VersionSpec &, const std::string & var,
+ std::tr1::shared_ptr<const PortageRepositoryProfile>) const = 0;
+
+ virtual void install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &, std::tr1::shared_ptr<const PortageRepositoryProfile>) const = 0;
+ };
+
+ /**
+ * Thrown if a repository of the specified type does not exist.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grprepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE NoSuchPortageRepositoryEntriesType : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ NoSuchPortageRepositoryEntriesType(const std::string & format) throw ();
+ };
+
+ /**
+ * Virtual constructor for PortageRepositoryEntries.
+ *
+ * \ingroup grprepository
+ */
+ class PortageRepositoryEntriesMaker :
+ public VirtualConstructor<std::string,
+ std::tr1::shared_ptr<PortageRepositoryEntries> (*) (const Environment * const, PortageRepository * const,
+ const PortageRepositoryParams &),
+ virtual_constructor_not_found::ThrowException<NoSuchPortageRepositoryEntriesType> >,
+ public InstantiationPolicy<PortageRepositoryEntriesMaker, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<PortageRepositoryEntriesMaker, instantiation_method::SingletonTag>;
+
+ private:
+ PortageRepositoryEntriesMaker();
+ };
+
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_entry.cc b/0.18.0/paludis/repositories/portage/portage_repository_entry.cc
new file mode 100644
index 000000000..ea568cd1f
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_entry.cc
@@ -0,0 +1,32 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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 "portage_repository_metadata.hh"
+
+using namespace paludis;
+
+PortageRepositoryMetadata::PortageRepositoryMetadata(const std::string & ext) :
+ _ext(ext)
+{
+}
+
+PortageRepositoryMetadata::~PortageRepositoryMetadata()
+{
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_exceptions.cc b/0.18.0/paludis/repositories/portage/portage_repository_exceptions.cc
new file mode 100644
index 000000000..f8e118697
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_exceptions.cc
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006 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 "portage_repository_exceptions.hh"
+
+using namespace paludis;
+
+PortageRepositoryConfigurationError::PortageRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("Portage repository configuration error: " + msg)
+{
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_exceptions.hh b/0.18.0/paludis/repositories/portage/portage_repository_exceptions.hh
new file mode 100644
index 000000000..945182e5c
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_exceptions.hh
@@ -0,0 +1,53 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006 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_PORTAGE_PORTAGE_REPOSITORY_EXCEPTIONS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_EXCEPTIONS_HH 1
+
+#include <paludis/util/exception.hh>
+
+/** \file
+ * Declaration for the PortageRepository exception classes.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ /**
+ * Thrown if invalid parameters are provided for
+ * PortageRepository::make_portage_repository.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE PortageRepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ PortageRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+
+
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_news.cc b/0.18.0/paludis/repositories/portage/portage_repository_news.cc
new file mode 100644
index 000000000..d36f5b3b1
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_news.cc
@@ -0,0 +1,282 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/portage/portage_repository.hh>
+#include <paludis/repositories/portage/portage_repository_news.hh>
+
+#include <paludis/config_file.hh>
+#include <paludis/environment.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+
+#include <set>
+#include <ostream>
+#include <fstream>
+#include <list>
+
+using namespace paludis;
+
+namespace paludis
+{
+ /**
+ * Implementation data for PortageRepositoryNews.
+ *
+ * \ingroup grpportagerepository
+ */
+ template<>
+ struct Implementation<PortageRepositoryNews>
+ {
+ const Environment * const environment;
+ const PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ const FSEntry skip_file;
+ const FSEntry unread_file;
+
+ Implementation(const Environment * const e, const PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k),
+ skip_file(params.root / "var" / "lib" / "paludis" / "news" /
+ ("news-" + stringify(portage_repository->name()) + ".skip")),
+ unread_file(params.root / "var" / "lib" / "paludis" / "news" /
+ ("news-" + stringify(portage_repository->name()) + ".unread"))
+ {
+ }
+ };
+}
+
+PortageRepositoryNews::PortageRepositoryNews(const Environment * const e, const PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ PrivateImplementationPattern<PortageRepositoryNews>(new Implementation<PortageRepositoryNews>(e, p, k))
+{
+}
+
+PortageRepositoryNews::~PortageRepositoryNews()
+{
+}
+
+void
+PortageRepositoryNews::update_news() const
+{
+ Context context("When updating news at location '" +
+ stringify(_imp->params.newsdir) + "' for repository '" +
+ stringify(_imp->portage_repository->name()) + "':");
+
+ if (! _imp->params.newsdir.is_directory())
+ return;
+
+ std::set<std::string> skip;
+
+ if (_imp->skip_file.is_regular_file())
+ {
+ Context local_context("When handling news skip file '" + stringify(
+ _imp->skip_file) + "':");
+ LineConfigFile s(_imp->skip_file);
+ std::copy(s.begin(), s.end(), std::inserter(skip, skip.end()));
+ }
+
+ for (DirIterator d(_imp->params.newsdir), d_end ; d != d_end ; ++d)
+ {
+ Context local_context("When handling news entry '" + stringify(*d) + "':");
+
+ if (! d->is_directory())
+ continue;
+ if (! (*d / (d->basename() + ".en.txt")).is_regular_file())
+ continue;
+
+ if (skip.end() != skip.find(d->basename()))
+ continue;
+
+ try
+ {
+ NewsFile news(*d / (d->basename() + ".en.txt"));
+ bool show(true);
+
+ if (news.begin_display_if_installed() != news.end_display_if_installed())
+ {
+ bool local_show(false);
+ for (NewsFile::DisplayIfInstalledIterator i(news.begin_display_if_installed()),
+ i_end(news.end_display_if_installed()) ; i != i_end ; ++i)
+ if (! _imp->environment->package_database()->query(PackageDepAtom(*i), is_installed_only,
+ qo_whatever)->empty())
+ local_show = true;
+ show &= local_show;
+ }
+
+ if (news.begin_display_if_keyword() != news.end_display_if_keyword())
+ {
+ bool local_show(false);
+ for (NewsFile::DisplayIfKeywordIterator i(news.begin_display_if_keyword()),
+ i_end(news.end_display_if_keyword()) ; i != i_end && ! local_show ; ++i)
+ if (*i == _imp->portage_repository->profile_variable("ARCH"))
+ local_show = true;
+ show &= local_show;
+ }
+
+ if (news.begin_display_if_profile() != news.end_display_if_profile())
+ {
+ bool local_show(false);
+ std::tr1::shared_ptr<const FSEntryCollection> c(_imp->params.profiles);
+ for (FSEntryCollection::Iterator p(c->begin()), p_end(c->end()) ; p != p_end ; ++p)
+ {
+ std::string profile(strip_leading_string(strip_trailing_string(
+ strip_leading_string(stringify(p->realpath()),
+ stringify(p->realpath())), "/"), "/"));
+ Log::get_instance()->message(ll_debug, lc_no_context,
+ "Profile path is '" + profile + "'");
+ for (NewsFile::DisplayIfProfileIterator i(news.begin_display_if_profile()),
+ i_end(news.end_display_if_profile()) ; i != i_end ; ++i)
+ if (profile == *i)
+ local_show = true;
+ }
+ show &= local_show;
+ }
+
+ if (show)
+ {
+ std::ofstream s(stringify(_imp->skip_file).c_str(),
+ std::ios::out | std::ios::app);
+ if (! s)
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Cannot append to news skip file '"
+ + stringify(_imp->skip_file) +
+ "', skipping news item '" + stringify(*d) + "'");
+
+ std::ofstream t(stringify(_imp->unread_file).c_str(),
+ std::ios::out | std::ios::app);
+ if (! t)
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Cannot append to unread file '"
+ + stringify(_imp->unread_file) +
+ "', skipping news item '" + stringify(*d) + "'");
+
+ if (s && t)
+ {
+ s << d->basename() << std::endl;
+ t << d->basename() << std::endl;
+ }
+ }
+ }
+ catch (const ConfigFileError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Skipping news item '"
+ + stringify(*d) + "' because of exception '" + e.message() + "' ("
+ + e.what() + ")");
+ }
+ }
+
+}
+
+namespace paludis
+{
+ /**
+ * Implementation data for NewsFile.
+ *
+ * \ingroup grpnewsconfigfile
+ */
+ template<>
+ struct Implementation<NewsFile>
+ {
+ mutable bool in_header;
+ mutable std::list<std::string> display_if_installed;
+ mutable std::list<std::string> display_if_keyword;
+ mutable std::list<std::string> display_if_profile;
+
+ Implementation() :
+ in_header(true)
+ {
+ }
+ };
+}
+
+NewsFile::NewsFile(const FSEntry & our_filename) :
+ ConfigFile(our_filename),
+ PrivateImplementationPattern<NewsFile>(new Implementation<NewsFile>)
+{
+ need_lines();
+}
+
+NewsFile::~NewsFile()
+{
+}
+
+void
+NewsFile::accept_line(const std::string & line) const
+{
+ if (_imp->in_header)
+ {
+ std::string::size_type p(line.find(':'));
+ if (std::string::npos == p)
+ _imp->in_header = false;
+ else
+ {
+ std::string k(strip_leading(strip_trailing(line.substr(0, p), " \t\n"), " \t\n"));
+ std::string v(strip_leading(strip_trailing(line.substr(p + 1), " \t\n"), " \t\n"));
+ if (k == "Display-If-Installed")
+ _imp->display_if_installed.push_back(v);
+ else if (k == "Display-If-Keyword")
+ _imp->display_if_keyword.push_back(v);
+ if (k == "Display-If-Profile")
+ _imp->display_if_profile.push_back(v);
+ }
+ }
+}
+
+NewsFile::DisplayIfInstalledIterator
+NewsFile::begin_display_if_installed() const
+{
+ return DisplayIfInstalledIterator(_imp->display_if_installed.begin());
+}
+
+NewsFile::DisplayIfInstalledIterator
+NewsFile::end_display_if_installed() const
+{
+ return DisplayIfInstalledIterator(_imp->display_if_installed.end());
+}
+
+NewsFile::DisplayIfKeywordIterator
+NewsFile::begin_display_if_keyword() const
+{
+ return DisplayIfKeywordIterator(_imp->display_if_keyword.begin());
+}
+
+NewsFile::DisplayIfKeywordIterator
+NewsFile::end_display_if_keyword() const
+{
+ return DisplayIfKeywordIterator(_imp->display_if_keyword.end());
+}
+
+NewsFile::DisplayIfProfileIterator
+NewsFile::begin_display_if_profile() const
+{
+ return DisplayIfProfileIterator(_imp->display_if_profile.begin());
+}
+
+NewsFile::DisplayIfProfileIterator
+NewsFile::end_display_if_profile() const
+{
+ return DisplayIfProfileIterator(_imp->display_if_profile.end());
+}
+
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_news.hh b/0.18.0/paludis/repositories/portage/portage_repository_news.hh
new file mode 100644
index 000000000..bd1b67d18
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_news.hh
@@ -0,0 +1,135 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PORTAGE_PORTAGE_REPOSITORY_NEWS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_NEWS_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/config_file.hh>
+
+/** \file
+ * Declaration for the PortageRepositoryNews class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class Environment;
+ class FSEntry;
+ class PortageRepository;
+
+ /**
+ * Holds the news/ data for a PortageRepository instance.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE PortageRepositoryNews :
+ private PrivateImplementationPattern<PortageRepositoryNews>,
+ private InstantiationPolicy<PortageRepositoryNews, instantiation_method::NonCopyableTag>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ PortageRepositoryNews(const Environment * const, const PortageRepository * const,
+ const PortageRepositoryParams &);
+ ~PortageRepositoryNews();
+
+ ///\}
+
+ void update_news() const;
+ };
+
+ /**
+ * A NewsFile represents a GLEP 42 news file.
+ *
+ * \ingroup grpnewsconfigfile
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE NewsFile :
+ protected ConfigFile,
+ private PrivateImplementationPattern<NewsFile>
+ {
+ protected:
+ void accept_line(const std::string &) const;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ /**
+ * Constructor, from a filename.
+ */
+ NewsFile(const FSEntry & filename);
+
+ ~NewsFile();
+
+ ///\}
+
+ ///\name Iterate over our Display-If-Installed headers
+ ///\{
+
+ /// Tag for DisplayIfInstalledIterator.
+ struct DisplayIfInstalledIteratorTag;
+
+ typedef libwrapiter::ForwardIterator<DisplayIfInstalledIteratorTag,
+ const std::string> DisplayIfInstalledIterator;
+
+ DisplayIfInstalledIterator begin_display_if_installed() const;
+
+ DisplayIfInstalledIterator end_display_if_installed() const;
+
+ ///\}
+
+ ///\name Iterate over our Display-If-Keyword headers
+ ///\{
+
+ /// Tag for DisplayIfKeywordIterator.
+ struct DisplayIfKeywordIteratorTag;
+
+ typedef libwrapiter::ForwardIterator<DisplayIfKeywordIteratorTag,
+ const std::string> DisplayIfKeywordIterator;
+
+ DisplayIfKeywordIterator begin_display_if_keyword() const;
+
+ DisplayIfKeywordIterator end_display_if_keyword() const;
+
+ ///\}
+
+ ///\name Iterate over our Display-If-Profile headers
+ ///\{
+
+ /// Tag for DisplayIfProfileIterator.
+ struct DisplayIfProfileIteratorTag;
+
+ typedef libwrapiter::ForwardIterator<DisplayIfProfileIteratorTag,
+ const std::string> DisplayIfProfileIterator;
+
+ DisplayIfProfileIterator begin_display_if_profile() const;
+
+ DisplayIfProfileIterator end_display_if_profile() const;
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_params.cc b/0.18.0/paludis/repositories/portage/portage_repository_params.cc
new file mode 100644
index 000000000..d52072565
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_params.cc
@@ -0,0 +1,8 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+#include "portage_repository_params.hh"
+
+using namespace paludis;
+
+#include <paludis/repositories/portage/portage_repository_params-sr.cc>
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_params.hh b/0.18.0/paludis/repositories/portage/portage_repository_params.hh
new file mode 100644
index 000000000..538176680
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_params.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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_PORTAGE_PORTAGE_REPOSITORY_PARAMS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_PARAMS_HH 1
+
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/collection.hh>
+#include <paludis/util/sr.hh>
+
+/** \file
+ * Declaration for the PortageRepositoryParams class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class Environment;
+ class PackageDatabase;
+
+#include <paludis/repositories/portage/portage_repository_params-sr.hh>
+
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_params.sr b/0.18.0/paludis/repositories/portage/portage_repository_params.sr
new file mode 100644
index 000000000..8363d64e0
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_params.sr
@@ -0,0 +1,36 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_PortageRepositoryParams()
+{
+ key entry_format std::string
+ key environment "Environment *"
+ key location FSEntry
+ key profiles "std::tr1::shared_ptr<const FSEntryCollection>"
+ key cache FSEntry
+ key write_cache FSEntry
+ key names_cache FSEntry
+ key distdir FSEntry
+ key pkgdir FSEntry
+ key eclassdirs "std::tr1::shared_ptr<const FSEntryCollection>"
+ key setsdir FSEntry
+ key securitydir FSEntry
+ key newsdir FSEntry
+ key sync std::string
+ key sync_options std::string
+ key root FSEntry
+ key buildroot FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a PortageRepository
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_profile.cc b/0.18.0/paludis/repositories/portage/portage_repository_profile.cc
new file mode 100644
index 000000000..a411d9ca7
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_profile.cc
@@ -0,0 +1,715 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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/portage/portage_repository_profile.hh>
+#include <paludis/repositories/portage/portage_repository_profile_file.hh>
+#include <paludis/repositories/portage/portage_repository_exceptions.hh>
+
+#include <paludis/util/log.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/save.hh>
+
+#include <paludis/config_file.hh>
+#include <paludis/environment.hh>
+#include <paludis/match_package.hh>
+#include <paludis/hashed_containers.hh>
+
+#include <list>
+#include <algorithm>
+#include <set>
+
+#include <strings.h>
+#include <ctype.h>
+
+using namespace paludis;
+
+namespace
+{
+ typedef MakeHashedSet<UseFlagName>::Type UseFlagSet;
+ typedef MakeHashedMap<std::string, std::string>::Type EnvironmentVariablesMap;
+ typedef MakeHashedMap<QualifiedPackageName, std::tr1::shared_ptr<const PackageDepAtom> >::Type VirtualsMap;
+ typedef MakeHashedMap<QualifiedPackageName, std::list<std::tr1::shared_ptr<const PackageDepAtom> > >::Type PackageMaskMap;
+
+ typedef MakeHashedMap<UseFlagName, bool>::Type FlagStatusMap;
+ typedef std::list<std::pair<std::tr1::shared_ptr<const PackageDepAtom>, FlagStatusMap> > PackageFlagStatusMapList;
+
+ struct StackedValues
+ {
+ std::string origin;
+
+ FlagStatusMap use_mask;
+ FlagStatusMap use_force;
+ PackageFlagStatusMapList package_use;
+ PackageFlagStatusMapList package_use_mask;
+ PackageFlagStatusMapList package_use_force;
+
+ StackedValues(const std::string & o) :
+ origin(o)
+ {
+ }
+ };
+
+ typedef std::list<StackedValues> StackedValuesList;
+}
+
+namespace paludis
+{
+ /**
+ * Implementation for PortageRepositoryProfile.
+ *
+ * \ingroup grpportagerepository
+ * \see PortageRepositoryProfile
+ */
+ template<>
+ class Implementation<PortageRepositoryProfile>
+ {
+ private:
+ void load_profile_directory_recursively(const FSEntry & dir);
+ void load_profile_parent(const FSEntry & dir);
+ void load_profile_make_defaults(const FSEntry & dir);
+
+ void load_basic_use_file(const FSEntry & file, FlagStatusMap & m);
+ void load_atom_use_file(const FSEntry & file, PackageFlagStatusMapList & m);
+
+ void add_use_expand_to_use();
+ void make_vars_from_file_vars();
+ void handle_profile_arch_var();
+ void load_special_make_defaults_vars();
+
+ ProfileFile packages_file;
+ ProfileFile virtuals_file;
+ ProfileFile package_mask_file;
+
+ bool is_incremental(const std::string & s) const;
+
+
+ public:
+ ///\name General variables
+ ///\{
+
+ const Environment * const env;
+
+ ///\}
+
+ ///\name Environment variables
+ ///\{
+
+ EnvironmentVariablesMap environment_variables;
+
+ ///\}
+
+ ///\name System package set
+ ///\{
+
+ std::tr1::shared_ptr<AllDepAtom> system_packages;
+ std::tr1::shared_ptr<GeneralSetDepTag> system_tag;
+
+ ///\}
+
+ ///\name Virtuals
+ ///\{
+
+ VirtualsMap virtuals;
+
+ ///\}
+
+ ///\name USE related values
+ ///\{
+
+ UseFlagSet use;
+ UseFlagSet use_expand;
+ UseFlagSet use_expand_hidden;
+ StackedValuesList stacked_values_list;
+
+ ///\}
+
+ ///\name Masks
+ ///\{
+
+ PackageMaskMap package_mask;
+
+ ///\}
+
+ ///\name Basic operations
+ ///\{
+
+ Implementation(const Environment * const e, const RepositoryName & name,
+ const FSEntryCollection & dirs) :
+ env(e),
+ system_packages(new AllDepAtom),
+ system_tag(new GeneralSetDepTag(SetName("system"), stringify(name)))
+ {
+ for (FSEntryCollection::Iterator d(dirs.begin()), d_end(dirs.end()) ;
+ d != d_end ; ++d)
+ load_profile_directory_recursively(*d);
+
+ make_vars_from_file_vars();
+ load_special_make_defaults_vars();
+ add_use_expand_to_use();
+ handle_profile_arch_var();
+ }
+
+ ~Implementation()
+ {
+ }
+
+ ///\}
+ };
+}
+
+void
+Implementation<PortageRepositoryProfile>::load_profile_directory_recursively(const FSEntry & dir)
+{
+ Context context("When adding profile directory '" + stringify(dir) + ":");
+ Log::get_instance()->message(ll_debug, lc_context, "Loading profile directory '" + stringify(dir) + "'");
+
+ if (! dir.is_directory())
+ {
+ Log::get_instance()->message(ll_warning, lc_context,
+ "Profile component '" + stringify(dir) + "' is not a directory");
+ return;
+ }
+
+ stacked_values_list.push_back(StackedValues(stringify(dir)));
+
+ load_profile_parent(dir);
+ load_profile_make_defaults(dir);
+
+ load_basic_use_file(dir / "use.mask", stacked_values_list.back().use_mask);
+ load_basic_use_file(dir / "use.force", stacked_values_list.back().use_force);
+ load_atom_use_file(dir / "package.use", stacked_values_list.back().package_use);
+ load_atom_use_file(dir / "package.use.mask", stacked_values_list.back().package_use_mask);
+ load_atom_use_file(dir / "package.use.force", stacked_values_list.back().package_use_force);
+
+ packages_file.add_file(dir / "packages");
+ virtuals_file.add_file(dir / "virtuals");
+ package_mask_file.add_file(dir / "package.mask");
+}
+
+void
+Implementation<PortageRepositoryProfile>::load_profile_parent(const FSEntry & dir)
+{
+ Context context("When handling parent file for profile directory '" + stringify(dir) + ":");
+
+ if (! (dir / "parent").exists())
+ return;
+
+ LineConfigFile file(dir / "parent");
+
+ LineConfigFile::Iterator i(file.begin()), i_end(file.end());
+ if (i == i_end)
+ Log::get_instance()->message(ll_warning, lc_context, "parent file is empty");
+ else
+ for ( ; i != i_end ; ++i)
+ {
+ FSEntry parent_dir(dir);
+ do
+ {
+ try
+ {
+ parent_dir = (parent_dir / *i).realpath();
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping parent '"
+ + *i + "' due to exception: " + e.message() + " (" + e.what() + ")");
+ continue;
+ }
+
+ load_profile_directory_recursively(parent_dir);
+
+ } while (false);
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::load_profile_make_defaults(const FSEntry & dir)
+{
+ Context context("When handling make.defaults file for profile directory '" + stringify(dir) + ":");
+
+ if (! (dir / "make.defaults").exists())
+ return;
+
+ KeyValueConfigFile file(dir / "make.defaults");
+
+ for (KeyValueConfigFile::Iterator k(file.begin()), k_end(file.end()) ;
+ k != k_end ; ++k)
+ {
+ if (is_incremental(k->first))
+ {
+ std::list<std::string> val, val_add;
+ WhitespaceTokeniser::get_instance()->tokenise(environment_variables[k->first], std::back_inserter(val));
+ WhitespaceTokeniser::get_instance()->tokenise(k->second, std::back_inserter(val_add));
+
+ for (std::list<std::string>::const_iterator v(val_add.begin()), v_end(val_add.end()) ;
+ v != v_end ; ++v)
+ {
+ if (v->empty())
+ continue;
+ if (*v == "-*")
+ val.clear();
+ else if ('-' == v->at(0))
+ val.remove(v->substr(1));
+ else
+ val.push_back(*v);
+ }
+
+ environment_variables[k->first] = join(val.begin(), val.end(), " ");
+ }
+ else
+ environment_variables[k->first] = k->second;
+
+ Log::get_instance()->message(ll_debug, lc_context, "Profile environment variable '" +
+ stringify(k->first) + "' is now '" + stringify(environment_variables[k->first]) + "'");
+ }
+
+ try
+ {
+ use_expand.clear();
+ WhitespaceTokeniser::get_instance()->tokenise(environment_variables["USE_EXPAND"],
+ create_inserter<UseFlagName>(std::inserter(use_expand, use_expand.end())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE_EXPAND failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::load_special_make_defaults_vars()
+{
+ try
+ {
+ use.clear();
+ WhitespaceTokeniser::get_instance()->tokenise(environment_variables["USE"],
+ create_inserter<UseFlagName>(std::inserter(use, use.end())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ use_expand.clear();
+ WhitespaceTokeniser::get_instance()->tokenise(environment_variables["USE_EXPAND"],
+ create_inserter<UseFlagName>(std::inserter(use_expand, use_expand.end())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE_EXPAND failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+ try
+ {
+ use_expand_hidden.clear();
+ WhitespaceTokeniser::get_instance()->tokenise(environment_variables["USE_EXPAND_HIDDEN"],
+ create_inserter<UseFlagName>(std::inserter(use_expand_hidden, use_expand_hidden.end())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE_EXPAND_HIDDEN failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+}
+
+bool
+Implementation<PortageRepositoryProfile>::is_incremental(const std::string & s) const
+{
+ try
+ {
+ return (s == "USE") || (s == "USE_EXPAND") || (s == "USE_EXPAND_HIDDEN")
+ || (s == "CONFIG_PROTECT") || (s == "CONFIG_PROTECT_MASK")
+ || (use_expand.end() != use_expand.find(UseFlagName(s)));
+ }
+ catch (const NameError &)
+ {
+ return (s == "USE") || (s == "USE_EXPAND") || (s == "USE_EXPAND_HIDDEN")
+ || (s == "CONFIG_PROTECT") || (s == "CONFIG_PROTECT_MASK");
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::make_vars_from_file_vars()
+{
+ try
+ {
+ for (ProfileFile::Iterator i(packages_file.begin()), i_end(packages_file.end()) ; i != i_end ; ++i)
+ {
+ if (0 != i->compare(0, 1, "*", 0, 1))
+ continue;
+
+ Context context_atom("When parsing '" + *i + "':");
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(i->substr(1)));
+ atom->set_tag(system_tag);
+ system_packages->add_child(atom);
+ }
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading packages "
+ " failed due to exception: " + e.message() + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ for (ProfileFile::Iterator line(virtuals_file.begin()), line_end(virtuals_file.end()) ;
+ line != line_end ; ++line)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(tokens));
+ if (tokens.size() < 2)
+ continue;
+
+ QualifiedPackageName v(tokens[0]);
+ virtuals.erase(v);
+ virtuals.insert(std::make_pair(v, std::tr1::shared_ptr<PackageDepAtom>(new PackageDepAtom(tokens[1]))));
+ }
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading virtuals "
+ " failed due to exception: " + e.message() + " (" + e.what() + ")");
+ }
+
+ for (ProfileFile::Iterator line(package_mask_file.begin()), line_end(package_mask_file.end()) ;
+ line != line_end ; ++line)
+ {
+ if (line->empty())
+ continue;
+
+ try
+ {
+ std::tr1::shared_ptr<const PackageDepAtom> a(new PackageDepAtom(*line));
+ package_mask[a->package()].push_back(a);
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading package.mask atom '"
+ + stringify(*line) + "' failed due to exception '" + e.message() + "' ("
+ + e.what() + ")");
+ }
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::load_basic_use_file(const FSEntry & file, FlagStatusMap & m)
+{
+ if (! file.exists())
+ return;
+
+ Context context("When loading basic use file '" + stringify(file) + ":");
+ LineConfigFile f(file);
+ for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ;
+ line != line_end ; ++line)
+ {
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(tokens));
+
+ for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ {
+ try
+ {
+ if (t->empty())
+ continue;
+ if ('-' == t->at(0))
+ m[UseFlagName(t->substr(1))] = false;
+ else
+ m[UseFlagName(*t)] = true;
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Ignoring token '"
+ + *t + "' due to exception '" + e.message() + "' (" + e.what() + ")");
+ }
+ }
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::load_atom_use_file(const FSEntry & file, PackageFlagStatusMapList & m)
+{
+ if (! file.exists())
+ return;
+
+ Context context("When loading atomised use file '" + stringify(file) + ":");
+ LineConfigFile f(file);
+ for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ;
+ line != line_end ; ++line)
+ {
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(tokens));
+
+ if (tokens.empty())
+ continue;
+
+ try
+ {
+ std::tr1::shared_ptr<const PackageDepAtom> atom(new PackageDepAtom(*tokens.begin()));
+ PackageFlagStatusMapList::iterator n(m.insert(m.end(), std::make_pair(atom, FlagStatusMap())));
+
+ for (std::list<std::string>::const_iterator t(next(tokens.begin())), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ {
+ try
+ {
+ if (t->empty())
+ continue;
+ if ('-' == t->at(0))
+ n->second[UseFlagName(t->substr(1))] = false;
+ else
+ n->second[UseFlagName(*t)] = true;
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Ignoring token '"
+ + *t + "' due to exception '" + e.message() + "' (" + e.what() + ")");
+ }
+ }
+ }
+ catch (const PackageDepAtomError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Ignoring line '"
+ + *line + "' due to exception '" + e.message() + "' (" + e.what() + ")");
+ }
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::add_use_expand_to_use()
+{
+ Context context("When adding USE_EXPAND to USE:");
+
+ stacked_values_list.push_back(StackedValues("use_expand special values"));
+
+ for (UseFlagSet::const_iterator x(use_expand.begin()), x_end(use_expand.end()) ;
+ x != x_end ; ++x)
+ {
+ std::string lower_x;
+ std::transform(x->data().begin(), x->data().end(), std::back_inserter(lower_x),
+ &::tolower);
+
+ std::list<std::string> uses;
+ WhitespaceTokeniser::get_instance()->tokenise(environment_variables[stringify(*x)],
+ std::back_inserter(uses));
+ for (std::list<std::string>::const_iterator u(uses.begin()), u_end(uses.end()) ;
+ u != u_end ; ++u)
+ use.insert(UseFlagName(lower_x + "_" + *u));
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::handle_profile_arch_var()
+{
+ Context context("When handling profile ARCH variable:");
+
+ std::string arch_s(environment_variables["ARCH"]);
+ if (arch_s.empty())
+ throw PortageRepositoryConfigurationError("ARCH variable is unset or empty");
+
+ stacked_values_list.push_back(StackedValues("arch special values"));
+ try
+ {
+ UseFlagName arch(arch_s);
+
+ use.insert(arch);
+ stacked_values_list.back().use_force[arch] = true;
+ }
+ catch (const NameError &)
+ {
+ throw PortageRepositoryConfigurationError("ARCH variable has invalid value '" + arch_s + "'");
+ }
+}
+
+PortageRepositoryProfile::PortageRepositoryProfile(
+ const Environment * const env, const RepositoryName & name, const FSEntryCollection & location) :
+ PrivateImplementationPattern<PortageRepositoryProfile>(
+ new Implementation<PortageRepositoryProfile>(env, name, location))
+{
+}
+
+PortageRepositoryProfile::~PortageRepositoryProfile()
+{
+}
+
+bool
+PortageRepositoryProfile::use_masked(const UseFlagName & u,
+ const PackageDatabaseEntry * const e) const
+{
+ bool result(false);
+ for (StackedValuesList::const_iterator i(_imp->stacked_values_list.begin()),
+ i_end(_imp->stacked_values_list.end()) ; i != i_end ; ++i)
+ {
+ FlagStatusMap::const_iterator f(i->use_mask.find(u));
+ if (i->use_mask.end() != f)
+ result = f->second;
+
+ if (e)
+ for (PackageFlagStatusMapList::const_iterator g(i->package_use_mask.begin()),
+ g_end(i->package_use_mask.end()) ; g != g_end ; ++g)
+ {
+ if (! match_package(*_imp->env, *g->first, *e))
+ continue;
+
+ FlagStatusMap::const_iterator h(g->second.find(u));
+ if (g->second.end() != h)
+ result = h->second;
+ }
+ }
+
+ return result;
+}
+
+bool
+PortageRepositoryProfile::use_forced(const UseFlagName & u,
+ const PackageDatabaseEntry * const e) const
+{
+ bool result(false);
+ for (StackedValuesList::const_iterator i(_imp->stacked_values_list.begin()),
+ i_end(_imp->stacked_values_list.end()) ; i != i_end ; ++i)
+ {
+ FlagStatusMap::const_iterator f(i->use_force.find(u));
+ if (i->use_force.end() != f)
+ result = f->second;
+
+ if (e)
+ for (PackageFlagStatusMapList::const_iterator g(i->package_use_force.begin()),
+ g_end(i->package_use_force.end()) ; g != g_end ; ++g)
+ {
+ if (! match_package(*_imp->env, *g->first, *e))
+ continue;
+
+ FlagStatusMap::const_iterator h(g->second.find(u));
+ if (g->second.end() != h)
+ result = h->second;
+ }
+ }
+
+ return result;
+}
+
+UseFlagState
+PortageRepositoryProfile::use_state_ignoring_masks(const UseFlagName & u,
+ const PackageDatabaseEntry * const e) const
+{
+ UseFlagState result(use_unspecified);
+
+ result = _imp->use.end() != _imp->use.find(u) ? use_enabled : use_unspecified;
+
+ for (StackedValuesList::const_iterator i(_imp->stacked_values_list.begin()),
+ i_end(_imp->stacked_values_list.end()) ; i != i_end ; ++i)
+ {
+ if (e)
+ for (PackageFlagStatusMapList::const_iterator g(i->package_use.begin()),
+ g_end(i->package_use.end()) ; g != g_end ; ++g)
+ {
+ if (! match_package(*_imp->env, *g->first, *e))
+ continue;
+
+ FlagStatusMap::const_iterator h(g->second.find(u));
+ if (g->second.end() != h)
+ result = h->second ? use_enabled : use_disabled;
+ }
+ }
+
+ return result;
+}
+
+std::string
+PortageRepositoryProfile::environment_variable(const std::string & s) const
+{
+ EnvironmentVariablesMap::const_iterator i(_imp->environment_variables.find(s));
+ if (_imp->environment_variables.end() == i)
+ {
+ Log::get_instance()->message(ll_debug, lc_no_context, "Environment variable '" + s + "' is unset");
+ return "";
+ }
+ else
+ {
+ Log::get_instance()->message(ll_debug, lc_no_context, "Environment variable '" + s +
+ "' is '" + i->second + "'");
+ return i->second;
+ }
+}
+
+std::tr1::shared_ptr<AllDepAtom>
+PortageRepositoryProfile::system_packages() const
+{
+ return _imp->system_packages;
+}
+
+PortageRepositoryProfile::UseExpandIterator
+PortageRepositoryProfile::begin_use_expand() const
+{
+ return UseExpandIterator(_imp->use_expand.begin());
+}
+
+PortageRepositoryProfile::UseExpandIterator
+PortageRepositoryProfile::end_use_expand() const
+{
+ return UseExpandIterator(_imp->use_expand.end());
+}
+
+PortageRepositoryProfile::UseExpandIterator
+PortageRepositoryProfile::begin_use_expand_hidden() const
+{
+ return UseExpandIterator(_imp->use_expand_hidden.begin());
+}
+
+PortageRepositoryProfile::UseExpandIterator
+PortageRepositoryProfile::end_use_expand_hidden() const
+{
+ return UseExpandIterator(_imp->use_expand_hidden.end());
+}
+
+PortageRepositoryProfile::VirtualsIterator
+PortageRepositoryProfile::begin_virtuals() const
+{
+ return VirtualsIterator(_imp->virtuals.begin());
+}
+
+PortageRepositoryProfile::VirtualsIterator
+PortageRepositoryProfile::end_virtuals() const
+{
+ return VirtualsIterator(_imp->virtuals.end());
+}
+
+bool
+PortageRepositoryProfile::profile_masked(const QualifiedPackageName & n,
+ const VersionSpec & v, const RepositoryName & r) const
+{
+ PackageMaskMap::const_iterator rr(_imp->package_mask.find(n));
+ if (_imp->package_mask.end() == rr)
+ return false;
+ else
+ {
+ PackageDatabaseEntry dbe(n, v, r);
+ for (std::list<std::tr1::shared_ptr<const PackageDepAtom> >::const_iterator k(rr->second.begin()),
+ k_end(rr->second.end()) ; k != k_end ; ++k)
+ if (match_package(*_imp->env, **k, dbe))
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_profile.hh b/0.18.0/paludis/repositories/portage/portage_repository_profile.hh
new file mode 100644
index 000000000..e914b0a88
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_profile.hh
@@ -0,0 +1,127 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 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_PORTAGE_PORTAGE_REPOSITORY_PROFILE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_PROFILE_HH 1
+
+#include <paludis/dep_atom.hh>
+#include <paludis/package_database_entry.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/instantiation_policy.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <string>
+
+/** \file
+ * Declaration for the PortageRepositoryProfile class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class Environment;
+
+ /**
+ * Holds the profile data (but <em>not</em> the profiles/ top level data) for
+ * a PortageRepository instance.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE PortageRepositoryProfile :
+ private PrivateImplementationPattern<PortageRepositoryProfile>,
+ private InstantiationPolicy<PortageRepositoryProfile, instantiation_method::NonCopyableTag>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ PortageRepositoryProfile(const Environment * const env,
+ const RepositoryName & name,
+ const FSEntryCollection & location);
+ ~PortageRepositoryProfile();
+
+ ///\}
+
+ ///\name Use flag queries
+ ///\{
+
+ /// Is a use flag masked?
+ bool use_masked(const UseFlagName &, const PackageDatabaseEntry * const) const;
+
+ /// Is a use flag forced?
+ bool use_forced(const UseFlagName &, const PackageDatabaseEntry * const) const;
+
+ /// Use flag state, ignoring mask and force?
+ UseFlagState use_state_ignoring_masks(const UseFlagName &, const PackageDatabaseEntry * const) const;
+
+ ///\}
+
+ ///\name Iterate over USE_EXPAND, USE_EXPAND_HIDDEN
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<PortageRepositoryProfile, const UseFlagName> UseExpandIterator;
+
+ UseExpandIterator begin_use_expand() const;
+ UseExpandIterator end_use_expand() const;
+ UseExpandIterator begin_use_expand_hidden() const;
+ UseExpandIterator end_use_expand_hidden() const;
+
+ ///\}
+
+ ///\name Environment variable queries
+ ///\{
+
+ /// What is the value of an environment variable?
+ std::string environment_variable(const std::string &) const;
+
+ ///\}
+
+ ///\name Masks
+ ///\{
+
+ bool profile_masked(const QualifiedPackageName &, const VersionSpec &,
+ const RepositoryName &) const;
+
+ ///\}
+
+ ///\name System package set
+ ///\{
+
+ std::tr1::shared_ptr<AllDepAtom> system_packages() const;
+
+ ///\}
+
+ ///\name Virtuals
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<PortageRepositoryProfile,
+ const std::pair<const QualifiedPackageName, std::tr1::shared_ptr<const PackageDepAtom> > > VirtualsIterator;
+
+ VirtualsIterator begin_virtuals() const;
+ VirtualsIterator end_virtuals() const;
+ VirtualsIterator find_virtual() const;
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_profile_file.cc b/0.18.0/paludis/repositories/portage/portage_repository_profile_file.cc
new file mode 100644
index 000000000..04fa13a52
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_profile_file.cc
@@ -0,0 +1,85 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "portage_repository_profile_file.hh"
+#include <paludis/util/log.hh>
+#include <paludis/config_file.hh>
+#include <list>
+#include <algorithm>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ProfileFile>
+ {
+ std::list<std::string> lines;
+ };
+}
+
+void
+ProfileFile::add_file(const FSEntry & f)
+{
+ Context context("When adding profile configuration file '" + stringify(f) + "':");
+
+ if (! f.exists())
+ return;
+
+ LineConfigFile file(f);
+ for (LineConfigFile::Iterator line(file.begin()), line_end(file.end()) ; line != line_end ; ++line)
+ {
+ if (0 == line->compare(0, 1, "-", 0, 1))
+ {
+ std::list<std::string>::iterator i(std::find(_imp->lines.begin(), _imp->lines.end(), line->substr(1)));
+ if (_imp->lines.end() == i)
+ Log::get_instance()->message(ll_qa, lc_context, "No match for '" + *line + "'");
+ else
+ while (_imp->lines.end() != i)
+ {
+ _imp->lines.erase(i++);
+ i = std::find(i, _imp->lines.end(), line->substr(1));
+ }
+ }
+ else
+ _imp->lines.push_back(*line);
+ }
+}
+
+ProfileFile::ProfileFile() :
+ PrivateImplementationPattern<ProfileFile>(new Implementation<ProfileFile>)
+{
+}
+
+ProfileFile::~ProfileFile()
+{
+}
+
+ProfileFile::Iterator
+ProfileFile::begin() const
+{
+ return Iterator(_imp->lines.begin());
+}
+
+ProfileFile::Iterator
+ProfileFile::end() const
+{
+ return Iterator(_imp->lines.end());
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_profile_file.hh b/0.18.0/paludis/repositories/portage/portage_repository_profile_file.hh
new file mode 100644
index 000000000..baa6552f6
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_profile_file.hh
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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_PORTAGE_PORTAGE_REPOSITORY_PROFILE_FILE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_PROFILE_FILE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/fs_entry.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+namespace paludis
+{
+ /**
+ * A file in a PortageRepository profile.
+ *
+ * Handles -lines, comments, inherits automatically.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE ProfileFile :
+ private PrivateImplementationPattern<ProfileFile>
+ {
+ public:
+ ProfileFile();
+ ~ProfileFile();
+
+ void add_file(const FSEntry &);
+
+ typedef libwrapiter::ForwardIterator<ProfileFile, const std::string> Iterator;
+ Iterator begin() const;
+ Iterator end() const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_sets.cc b/0.18.0/paludis/repositories/portage/portage_repository_sets.cc
new file mode 100644
index 000000000..ed80a26c9
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_sets.cc
@@ -0,0 +1,370 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/portage/portage_repository.hh>
+#include <paludis/repositories/portage/portage_repository_sets.hh>
+#include <paludis/repositories/portage/glsa.hh>
+
+#include <paludis/dep_list/dep_list.hh>
+#include <paludis/environment.hh>
+#include <paludis/config_file.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <list>
+#include <set>
+
+#include "config.h"
+
+using namespace paludis;
+
+namespace paludis
+{
+ /**
+ * Implementation data for PortageRepositorySets.
+ *
+ * \ingroup grpportagerepository
+ */
+ template<>
+ struct Implementation<PortageRepositorySets>
+ {
+ const Environment * const environment;
+ const PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ Implementation(const Environment * const e, const PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k)
+ {
+ }
+ };
+}
+
+PortageRepositorySets::PortageRepositorySets(const Environment * const e, const PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ PrivateImplementationPattern<PortageRepositorySets>(new Implementation<PortageRepositorySets>(e, p, k))
+{
+}
+
+PortageRepositorySets::~PortageRepositorySets()
+{
+}
+
+
+std::tr1::shared_ptr<DepAtom>
+PortageRepositorySets::package_set(const SetName & s) const
+{
+ if ("system" == s.data())
+ throw InternalError(PALUDIS_HERE, "system set should've been handled by PortageRepository");
+ else if ("security" == s.data())
+ return security_set(false);
+ else if ("insecurity" == s.data())
+ return security_set(true);
+ else if ((_imp->params.setsdir / (stringify(s) + ".conf")).exists())
+ {
+ std::tr1::shared_ptr<GeneralSetDepTag> tag(new GeneralSetDepTag(s, stringify(_imp->portage_repository->name())));
+
+ FSEntry ff(_imp->params.setsdir / (stringify(s) + ".conf"));
+ Context context("When loading package set '" + stringify(s) + "' from '" + stringify(ff) + "':");
+
+ std::tr1::shared_ptr<AllDepAtom> result(new AllDepAtom);
+ LineConfigFile f(ff);
+ for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ;
+ line != line_end ; ++line)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if (1 == tokens.size())
+ {
+ Log::get_instance()->message(ll_warning, lc_context,
+ "Line '" + *line + "' in set file '"
+ + stringify(ff) + "' does not specify '*' or '?', assuming '*'");
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(tokens.at(0)));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+ else if ("*" == tokens.at(0))
+ {
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(tokens.at(1)));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+ else if ("?" == tokens.at(0))
+ {
+ std::tr1::shared_ptr<PackageDepAtom> p(new PackageDepAtom(tokens.at(1)));
+ p->set_tag(tag);
+ if (! _imp->environment->package_database()->query(PackageDepAtom(p->package()),
+ is_installed_only, qo_whatever)->empty())
+ result->add_child(p);
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_context,
+ "Line '" + *line + "' in set file '"
+ + stringify(ff) + "' does not start with '*' or '?' token, skipping");
+
+ if (tokens.size() > 2)
+ Log::get_instance()->message(ll_warning, lc_context,
+ "Line '" + *line + "' in set file '"
+ + stringify(ff) + "' has trailing garbage");
+ }
+
+ return result;
+ }
+ else
+ return std::tr1::shared_ptr<DepAtom>();
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+PortageRepositorySets::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ std::tr1::shared_ptr<SetsCollection> result(new SetsCollection::Concrete);
+ result->insert(SetName("insecurity"));
+ result->insert(SetName("security"));
+ result->insert(SetName("system"));
+
+ try
+ {
+ std::list<FSEntry> repo_sets;
+ std::copy(DirIterator(_imp->params.setsdir), DirIterator(),
+ filter_inserter(std::back_inserter(repo_sets),
+ IsFileWithExtension(".conf")));
+
+ std::list<FSEntry>::const_iterator f(repo_sets.begin()),
+ f_end(repo_sets.end());
+
+ for ( ; f != f_end ; ++f)
+ try
+ {
+ result->insert(SetName(stringify(*f)));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping set '"
+ + stringify(*f) + "' due to exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ")");
+ }
+ }
+ catch (const paludis::DirOpenError &)
+ {
+ }
+
+ return result;
+}
+
+PackageDatabaseEntryCollection::Iterator
+PortageRepositorySets::find_best(PackageDatabaseEntryCollection & c, const PackageDatabaseEntry & e) const
+{
+ Context local("When finding best update for '" + stringify(e.name) + "-" +
+ stringify(e.version) + "':");
+ // Find an entry in c that matches e best. e is not in c.
+ QualifiedPackageName n(e.name);
+ SlotName s(_imp->environment->package_database()->fetch_repository(
+ e.repository)->version_metadata(e.name, e.version)->slot);
+ PackageDatabaseEntryCollection::Iterator i(c.begin()), i_end(c.end()), i_best(c.end());
+ for ( ; i != i_end; ++i)
+ {
+ if (n != i->name)
+ continue;
+ if (s != _imp->environment->package_database()->fetch_repository(
+ i->repository)->version_metadata(
+ i->name, i->version)->slot)
+ continue;
+
+ i_best = i;
+ }
+
+ return i_best;
+}
+
+namespace
+{
+ bool
+ match_range(const PackageDatabaseEntry & e, const GLSARange & r)
+ {
+ VersionOperatorValue our_op(static_cast<VersionOperatorValue>(-1));
+ std::string ver(r.version);
+ if (r.op == "le")
+ our_op = vo_less_equal;
+ if (r.op == "lt")
+ our_op = vo_less;
+ if (r.op == "eq")
+ {
+ if (! ver.empty() && '*' == ver.at(ver.length() - 1))
+ {
+ ver.erase(ver.length() - 1);
+ our_op = vo_equal_star;
+ }
+ else
+ our_op = vo_equal;
+ }
+ if (r.op == "gt")
+ our_op = vo_greater;
+ if (r.op == "ge")
+ our_op = vo_greater_equal;
+
+ if (-1 != our_op)
+ return (e.version.*(VersionOperator(our_op).as_version_spec_operator()))(VersionSpec(ver));
+
+ if (0 == r.op.compare(0, 1, "r"))
+ {
+ return (e.version.*(VersionOperator(vo_tilde).as_version_spec_operator()))(VersionSpec(ver)) &&
+ match_range(e, GLSARange::create().op(r.op.substr(1)).version(r.version));
+ }
+
+ throw GLSAError("Got bad op '" + r.op + "'");
+ }
+
+ bool
+ is_vulnerable(const GLSAPackage & glsa_pkg, const PackageDatabaseEntry & c)
+ {
+ /* a package is affected if it matches any vulnerable line, except if it matches
+ * any unaffected line. */
+ bool vulnerable(false);
+ for (GLSAPackage::RangesIterator r(glsa_pkg.begin_vulnerable()), r_end(glsa_pkg.end_vulnerable()) ;
+ r != r_end && ! vulnerable ; ++r)
+ if (match_range(c, *r))
+ vulnerable = true;
+
+ if (! vulnerable)
+ return false;
+
+ for (GLSAPackage::RangesIterator r(glsa_pkg.begin_unaffected()), r_end(glsa_pkg.end_unaffected()) ;
+ r != r_end && vulnerable ; ++r)
+ if (match_range(c, *r))
+ vulnerable = false;
+
+ return vulnerable;
+ }
+}
+
+std::tr1::shared_ptr<DepAtom>
+PortageRepositorySets::security_set(bool insecurity) const
+{
+ Context context("When building security or insecurity package set:");
+ std::tr1::shared_ptr<AllDepAtom> security_packages(new AllDepAtom);
+
+ if (!_imp->params.securitydir.is_directory())
+ return security_packages;
+
+ std::map<std::string, std::tr1::shared_ptr<GLSADepTag> > glsa_tags;
+
+ for (DirIterator f(_imp->params.securitydir), f_end ; f != f_end; ++f)
+ {
+ if (! IsFileWithExtension("glsa-", ".xml")(*f))
+ continue;
+
+ Context local_context("When parsing security advisory '" + stringify(*f) + "':");
+
+ try
+ {
+ std::tr1::shared_ptr<const GLSA> glsa(GLSA::create_from_xml_file(stringify(*f)));
+ Context local_local_context("When handling GLSA '" + glsa->id() + "' from '" +
+ stringify(*f) + "':");
+
+ for (GLSA::PackagesIterator glsa_pkg(glsa->begin_packages()),
+ glsa_pkg_end(glsa->end_packages()) ; glsa_pkg != glsa_pkg_end ; ++glsa_pkg)
+ {
+ std::tr1::shared_ptr<const PackageDatabaseEntryCollection> candidates(_imp->environment->package_database()->query(
+ PackageDepAtom(glsa_pkg->name()), insecurity ? is_any : is_installed_only,
+ qo_order_by_version));
+ for (PackageDatabaseEntryCollection::Iterator c(candidates->begin()), c_end(candidates->end()) ;
+ c != c_end ; ++c)
+ {
+ if (! is_vulnerable(*glsa_pkg, *c))
+ continue;
+
+ if (glsa_tags.end() == glsa_tags.find(glsa->id()))
+ glsa_tags.insert(std::make_pair(glsa->id(), std::tr1::shared_ptr<GLSADepTag>(
+ new GLSADepTag(glsa->id(), glsa->title()))));
+
+ if (insecurity)
+ {
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(
+ "=" + stringify(c->name) + "-" + stringify(c->version) +
+ "::" + stringify(c->repository)));
+ atom->set_tag(glsa_tags.find(glsa->id())->second);
+ security_packages->add_child(atom);
+ }
+ else
+ {
+ /* we need to find the best not vulnerable installable package that isn't masked
+ * that's in the same slot as our vulnerable installed package. */
+ bool ok(false);
+ SlotName wanted_slot(_imp->environment->package_database()->fetch_repository(
+ c->repository)->version_metadata(c->name, c->version)->slot);
+
+ std::tr1::shared_ptr<const PackageDatabaseEntryCollection> available(
+ _imp->environment->package_database()->query(PackageDepAtom(glsa_pkg->name()), is_installable_only,
+ qo_order_by_version));
+ for (PackageDatabaseEntryCollection::ReverseIterator r(available->rbegin()),
+ r_end(available->rend()) ; r != r_end ; ++r)
+ {
+ if (_imp->environment->mask_reasons(*r).any())
+ continue;
+ if (_imp->environment->package_database()->fetch_repository(r->repository)->version_metadata(
+ r->name, r->version)->slot != wanted_slot)
+ continue;
+ if (is_vulnerable(*glsa_pkg, *r))
+ continue;
+
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(
+ "=" + stringify(r->name) + "-" + stringify(r->version) +
+ "::" + stringify(r->repository)));
+ atom->set_tag(glsa_tags.find(glsa->id())->second);
+ security_packages->add_child(atom);
+ ok = true;
+ break;
+ }
+
+ if (! ok)
+ throw GLSAError("Could not determine upgrade path to resolve '"
+ + glsa->id() + ": " + glsa->title() + "' for package '"
+ + stringify(*c) + "'");
+ }
+ }
+ }
+ }
+ catch (const GLSAError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Cannot use GLSA '" +
+ stringify(*f) + "' due to exception '" + e.message() + "' (" + e.what() + ")");
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Cannot use GLSA '" +
+ stringify(*f) + "' due to exception '" + e.message() + "' (" + e.what() + ")");
+ }
+ }
+
+ return security_packages;
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_repository_sets.hh b/0.18.0/paludis/repositories/portage/portage_repository_sets.hh
new file mode 100644
index 000000000..12cbabd62
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_repository_sets.hh
@@ -0,0 +1,80 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_SETS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_SETS_HH 1
+
+#include <paludis/dep_atom.hh>
+#include <paludis/repository.hh>
+
+/** \file
+ * Declaration for the PortageRepositorySets class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class Environment;
+ class PortageRepository;
+
+ /**
+ * Holds the information about sets, except system, for a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE PortageRepositorySets :
+ private PrivateImplementationPattern<PortageRepositorySets>,
+ private InstantiationPolicy<PortageRepositorySets, instantiation_method::NonCopyableTag>
+ {
+ private:
+ PackageDatabaseEntryCollection::Iterator
+ find_best(PackageDatabaseEntryCollection & c, const PackageDatabaseEntry & e) const;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ PortageRepositorySets(const Environment * const env, const PortageRepository * const,
+ const PortageRepositoryParams &);
+ ~PortageRepositorySets();
+
+ ///\}
+
+ /**
+ * Fetch a package set other than system.
+ */
+ std::tr1::shared_ptr<DepAtom> package_set(const SetName & s) const;
+
+ /**
+ * Fetch the security or insecurity set.
+ */
+ std::tr1::shared_ptr<DepAtom> security_set(bool insecure) const;
+
+ /**
+ * Give a list of all the sets in this repo.
+ */
+ std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+ };
+}
+
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.cc b/0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.cc
new file mode 100644
index 000000000..a10d4bc99
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.cc
@@ -0,0 +1,45 @@
+/* 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 "portage_virtual_version_metadata.hh"
+#include <paludis/portage_dep_parser.hh>
+
+using namespace paludis;
+
+PortageVirtualVersionMetadata::PortageVirtualVersionMetadata(const SlotName & s,
+ const PackageDatabaseEntry & e) :
+ VersionMetadata(
+ VersionMetadataBase(s, "", "", "paludis-1"),
+ VersionMetadataCapabilities::create()
+ .virtual_interface(this)
+ .ebuild_interface(0)
+ .deps_interface(this)
+ .license_interface(0)
+ .cran_interface(0)
+ .origins_interface(0)
+ ),
+ VersionMetadataVirtualInterface(e),
+ VersionMetadataDepsInterface(&PortageDepParser::parse_depend)
+{
+}
+
+PortageVirtualVersionMetadata::~PortageVirtualVersionMetadata()
+{
+}
+
diff --git a/0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.hh b/0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.hh
new file mode 100644
index 000000000..79e602821
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/portage_virtual_version_metadata.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_PORTAGE_PORTAGE_VIRTUAL_VERSION_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_VIRTUAL_VERSION_METADATA_HH 1
+
+#include <paludis/version_metadata.hh>
+
+namespace paludis
+{
+ class PortageVirtualVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataVirtualInterface,
+ public VersionMetadataDepsInterface
+ {
+ public:
+ PortageVirtualVersionMetadata(const SlotName &, const PackageDatabaseEntry &);
+ virtual ~PortageVirtualVersionMetadata();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/registration.cc b/0.18.0/paludis/repositories/portage/registration.cc
new file mode 100644
index 000000000..1b80763a6
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/registration.cc
@@ -0,0 +1,62 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/portage/make_ebuild_repository.hh>
+#include <paludis/util/log.hh>
+#include "config.h"
+
+using namespace paludis;
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+namespace
+{
+ std::tr1::shared_ptr<Repository>
+ make_portage_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+ {
+ std::string repo_file = "?";
+ if (m->end() != m->find("repo_file"))
+ repo_file = m->find("repo_file")->second;
+
+ Context context("When creating repository using '" + repo_file + "':");
+
+ Log::get_instance()->message(ll_warning, lc_context, "Format 'portage' is "
+ "deprecated, use 'ebuild' instead");
+
+ return make_ebuild_repository_wrapped(env, m);
+ }
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("ebuild", &make_ebuild_repository_wrapped);
+ maker->register_maker("portage", &make_portage_repository);
+}
+
+#endif
+
+
diff --git a/0.18.0/paludis/repositories/portage/use_desc.cc b/0.18.0/paludis/repositories/portage/use_desc.cc
new file mode 100644
index 000000000..1899d867a
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/use_desc.cc
@@ -0,0 +1,95 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "use_desc.hh"
+#include <paludis/hashed_containers.hh>
+#include <paludis/name.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/config_file.hh>
+#include <paludis/package_database_entry.hh>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<UseDesc>
+ {
+ MakeHashedMap<std::string, std::string>::Type desc;
+
+ void add(const FSEntry & f, const std::string & prefix)
+ {
+ if (f.is_regular_file())
+ {
+ LineConfigFile ff(f);
+ for (LineConfigFile::Iterator line(ff.begin()), line_end(ff.end()) ;
+ line != line_end ; ++line)
+ {
+ std::string::size_type p(line->find(" - "));
+ if (std::string::npos == p)
+ continue;
+
+ desc.insert(std::make_pair(prefix + line->substr(0, p), line->substr(p + 3)));
+ }
+ }
+ }
+
+ Implementation(const FSEntry & f)
+ {
+ add(f / "use.desc", "");
+ add(f / "use.local.desc", "");
+
+ if ((f / "desc").is_directory())
+ for (DirIterator d(f / "desc"), d_end ; d != d_end ; ++d)
+ if (IsFileWithExtension(".desc")(*d))
+ add(*d, strip_trailing_string(d->basename(), ".desc") + "_");
+ }
+ };
+}
+
+UseDesc::UseDesc(const FSEntry & f) :
+ PrivateImplementationPattern<UseDesc>(new Implementation<UseDesc>(f))
+{
+}
+
+UseDesc::~UseDesc()
+{
+}
+
+std::string
+UseDesc::describe(const UseFlagName & f, const PackageDatabaseEntry * const e) const
+{
+ if (e)
+ {
+ MakeHashedMap<std::string, std::string>::Type::const_iterator i(
+ _imp->desc.find(stringify(e->name) + ":" + stringify(f)));
+ if (_imp->desc.end() != i)
+ return i->second;
+ }
+
+ MakeHashedMap<std::string, std::string>::Type::const_iterator i(_imp->desc.find(stringify(f)));
+ if (_imp->desc.end() != i)
+ return i->second;
+
+ return "";
+}
+
diff --git a/0.18.0/paludis/repositories/portage/use_desc.hh b/0.18.0/paludis/repositories/portage/use_desc.hh
new file mode 100644
index 000000000..64ffc0235
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/use_desc.hh
@@ -0,0 +1,59 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_PALUDIS_REPOSITORIES_PORTAGE_USE_DESC_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_PORTAGE_USE_DESC_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/name.hh>
+
+namespace paludis
+{
+ class FSEntry;
+ class PackageDatabaseEntry;
+
+ /**
+ * Implements use.desc options for PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+ class UseDesc :
+ private PrivateImplementationPattern<UseDesc>,
+ private InstantiationPolicy<UseDesc, instantiation_method::NonCopyableTag>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ UseDesc(const FSEntry &);
+ ~UseDesc();
+
+ ///\}
+
+ /**
+ * Describe the given use flag, possibly for the specified package.
+ *
+ * May return an empty string.
+ */
+ std::string describe(const UseFlagName &, const PackageDatabaseEntry * const) const;
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/xml_things.cc b/0.18.0/paludis/repositories/portage/xml_things.cc
new file mode 100644
index 000000000..50ba25682
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/xml_things.cc
@@ -0,0 +1,219 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 <libxml/tree.h>
+#include <libxml/parser.h>
+#include <paludis/repositories/portage/glsa.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/join.hh>
+#include <paludis/config_file.hh>
+#include <set>
+#include <list>
+
+using namespace paludis;
+
+extern "C"
+{
+ std::tr1::shared_ptr<GLSA> create_glsa_from_xml_file(const std::string &);
+}
+
+namespace
+{
+ std::string retarded_libxml_string_to_string(const xmlChar * const s)
+ {
+ return s ? stringify(reinterpret_cast<const char *>(s)) : "";
+ }
+
+ std::string normalise(const std::string & s)
+ {
+ std::list<std::string> words;
+ WhitespaceTokeniser::get_instance()->tokenise(s, std::back_inserter(words));
+ return join(words.begin(), words.end(), " ");
+ }
+
+ class Handler
+ {
+ private:
+ std::tr1::shared_ptr<GLSA> _glsa;
+
+ public:
+ Handler() :
+ _glsa(new GLSA)
+ {
+ }
+
+ void handle_glsa_attrs(xmlDocPtr doc, xmlAttr * const attr)
+ {
+ for (xmlAttr * a(attr) ; a ; a = a->next)
+ {
+ if (a->type == XML_ATTRIBUTE_NODE)
+ {
+ std::string name(retarded_libxml_string_to_string(a->name));
+ if (name == "id")
+ _glsa->set_id(normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
+ a->xmlChildrenNode, 1))));
+ }
+ }
+ }
+
+ void handle_package_name(xmlDocPtr doc, xmlAttr * const attr, std::string & str)
+ {
+ for (xmlAttr * a(attr) ; a ; a = a->next)
+ {
+ if (a->type == XML_ATTRIBUTE_NODE)
+ {
+ std::string name(retarded_libxml_string_to_string(a->name));
+ if (name == "name")
+ str = normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
+ a->xmlChildrenNode, 1)));
+ }
+ }
+ }
+
+ void handle_package_archs(xmlDocPtr doc, xmlAttr * const attr, std::tr1::shared_ptr<GLSAPackage> pkg)
+ {
+ for (xmlAttr * a(attr) ; a ; a = a->next)
+ {
+ if (a->type == XML_ATTRIBUTE_NODE)
+ {
+ std::string name(retarded_libxml_string_to_string(a->name));
+ if (name == "arch")
+ {
+ std::set<std::string> archs;
+ WhitespaceTokeniser::get_instance()->tokenise(retarded_libxml_string_to_string(
+ xmlNodeListGetString(doc, a->xmlChildrenNode, 1)),
+ std::inserter(archs, archs.end()));
+ archs.erase("*");
+ for (std::set<std::string>::const_iterator r(archs.begin()), r_end(archs.end()) ;
+ r != r_end ; ++r)
+ pkg->add_arch(UseFlagName(*r));
+ }
+ }
+ }
+ }
+
+ void handle_range_range(xmlDocPtr doc, xmlAttr * const attr, std::string & op)
+ {
+ for (xmlAttr * a(attr) ; a ; a = a->next)
+ {
+ if (a->type == XML_ATTRIBUTE_NODE)
+ {
+ std::string name(retarded_libxml_string_to_string(a->name));
+ if (name == "range")
+ op = normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
+ a->xmlChildrenNode, 1)));
+ }
+ }
+ }
+
+ void handle_package_children(xmlDocPtr doc, xmlNode * const node, std::tr1::shared_ptr<GLSAPackage> pkg)
+ {
+ for (xmlNode * n(node) ; n ; n = n->next)
+ {
+ if (n->type == XML_ELEMENT_NODE)
+ {
+ std::string name(retarded_libxml_string_to_string(n->name));
+ if (name == "unaffected" || name == "vulnerable")
+ {
+ std::string op;
+ handle_range_range(doc, n->properties, op);
+ std::string version(normalise(retarded_libxml_string_to_string(
+ xmlNodeListGetString(doc, n->xmlChildrenNode, 1))));
+ ((*pkg).*(name == "unaffected" ? &GLSAPackage::add_unaffected : &GLSAPackage::add_vulnerable))
+ (GLSARange::create().op(op).version(version));
+ }
+ else
+ handle_node(doc, n->children);
+ }
+ else
+ handle_node(doc, n->children);
+ }
+
+ }
+
+ void handle_node(xmlDocPtr doc, xmlNode * const node)
+ {
+ for (xmlNode * n(node) ; n ; n = n->next)
+ {
+ if (n->type == XML_ELEMENT_NODE)
+ {
+ std::string name(retarded_libxml_string_to_string(n->name));
+ if (name == "glsa")
+ {
+ handle_glsa_attrs(doc, n->properties);
+ handle_node(doc, n->children);
+ }
+ else if (name == "title")
+ _glsa->set_title(normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
+ n->xmlChildrenNode, 1))));
+ else if (name == "package")
+ {
+ std::string m;
+ handle_package_name(doc, n->properties, m);
+ std::tr1::shared_ptr<GLSAPackage> pkg(new GLSAPackage(QualifiedPackageName(m)));
+ handle_package_archs(doc, n->properties, pkg);
+ handle_package_children(doc, n->children, pkg);
+ _glsa->add_package(pkg);
+ }
+ else
+ handle_node(doc, n->children);
+ }
+ else
+ handle_node(doc, n->children);
+ }
+
+ }
+
+ std::tr1::shared_ptr<GLSA> glsa()
+ {
+ return _glsa;
+ }
+ };
+}
+
+std::tr1::shared_ptr<GLSA>
+create_glsa_from_xml_file(const std::string & filename)
+{
+ std::tr1::shared_ptr<xmlDoc> xml_doc(xmlReadFile(filename.c_str(), 0, 0), &xmlFreeDoc);
+ if (! xml_doc)
+ throw GLSAError("Could not parse GLSA", filename);
+
+ Handler h;
+ h.handle_node(xml_doc.get(), xmlDocGetRootElement(xml_doc.get()));
+ return h.glsa();
+}
+
+#ifndef MONOLITHIC
+
+namespace paludis
+{
+ class RepositoryMaker;
+}
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker *)
+{
+}
+
+#endif
+
diff --git a/0.18.0/paludis/repositories/portage/xml_things.hh b/0.18.0/paludis/repositories/portage/xml_things.hh
new file mode 100644
index 000000000..772def364
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/xml_things.hh
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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_PORTAGE_XML_THINGS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_XML_THINGS_HH 1
+
+#include <paludis/repositories/portage/glsa.hh>
+
+extern "C"
+{
+ GLSA::Pointer create_glsa_from_xml_file(const std::string &);
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/portage/xml_things_TEST.cc b/0.18.0/paludis/repositories/portage/xml_things_TEST.cc
new file mode 100644
index 000000000..e993de067
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/xml_things_TEST.cc
@@ -0,0 +1,92 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/portage/glsa.hh>
+#include <paludis/util/join.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct GLSA123456_78Test : TestCase
+ {
+ GLSA123456_78Test() : TestCase("glsa 123456-78") { }
+
+ void run()
+ {
+ std::tr1::shared_ptr<GLSA> glsa(GLSA::create_from_xml_file("xml_things_TEST_dir/glsa-123456-78.xml"));
+ TEST_CHECK(glsa);
+
+ TEST_CHECK_EQUAL("123456-78", glsa->id());
+ TEST_CHECK_EQUAL("Kittens: Too Adorable", glsa->title());
+
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages(), glsa->end_packages()));
+ TEST_CHECK_STRINGIFY_EQUAL("animal-feline/kitten", glsa->begin_packages()->name());
+ TEST_CHECK_STRINGIFY_EQUAL("0", std::distance(glsa->begin_packages()->begin_archs(),
+ glsa->begin_packages()->end_archs()));
+
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages()->begin_unaffected(),
+ glsa->begin_packages()->end_unaffected()));
+ TEST_CHECK_STRINGIFY_EQUAL("ge", glsa->begin_packages()->begin_unaffected()->op);
+ TEST_CHECK_STRINGIFY_EQUAL("1.23", glsa->begin_packages()->begin_unaffected()->version);
+
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages(), glsa->end_packages()));
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages()->begin_vulnerable(),
+ glsa->begin_packages()->end_vulnerable()));
+ TEST_CHECK_STRINGIFY_EQUAL("lt", glsa->begin_packages()->begin_vulnerable()->op);
+ TEST_CHECK_STRINGIFY_EQUAL("1.22", glsa->begin_packages()->begin_vulnerable()->version);
+ }
+ } glsa_test_123456_78;
+
+ struct GLSA987654_32Test : TestCase
+ {
+ GLSA987654_32Test() : TestCase("glsa 987654-32") { }
+
+ void run()
+ {
+ std::tr1::shared_ptr<GLSA> glsa(GLSA::create_from_xml_file("xml_things_TEST_dir/glsa-987654-32.xml"));
+ TEST_CHECK(glsa);
+
+ TEST_CHECK_EQUAL("987654-32", glsa->id());
+ TEST_CHECK_EQUAL("Python: Retarded", glsa->title());
+
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages(), glsa->end_packages()));
+ TEST_CHECK_STRINGIFY_EQUAL("dev-lang/python", glsa->begin_packages()->name());
+ TEST_CHECK_STRINGIFY_EQUAL("3", std::distance(glsa->begin_packages()->begin_archs(),
+ glsa->begin_packages()->end_archs()));
+ TEST_CHECK_STRINGIFY_EQUAL("mips,sparc,x86", join(glsa->begin_packages()->begin_archs(),
+ glsa->begin_packages()->end_archs(), ","));
+
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages()->begin_unaffected(),
+ glsa->begin_packages()->end_unaffected()));
+ TEST_CHECK_STRINGIFY_EQUAL("ge", glsa->begin_packages()->begin_unaffected()->op);
+ TEST_CHECK_STRINGIFY_EQUAL("12.34", glsa->begin_packages()->begin_unaffected()->version);
+
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages(), glsa->end_packages()));
+ TEST_CHECK_STRINGIFY_EQUAL("1", std::distance(glsa->begin_packages()->begin_vulnerable(),
+ glsa->begin_packages()->end_vulnerable()));
+ TEST_CHECK_STRINGIFY_EQUAL("lt", glsa->begin_packages()->begin_vulnerable()->op);
+ TEST_CHECK_STRINGIFY_EQUAL("12.34", glsa->begin_packages()->begin_vulnerable()->version);
+ }
+ } glsa_test_987654_32;
+}
+
diff --git a/0.18.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh b/0.18.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh
new file mode 100755
index 000000000..5e0843fa2
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d xml_things_TEST_dir ] ; then
+ rm -fr xml_things_TEST_dir
+else
+ true
+fi
+
+
+
diff --git a/0.18.0/paludis/repositories/portage/xml_things_TEST_setup.sh b/0.18.0/paludis/repositories/portage/xml_things_TEST_setup.sh
new file mode 100755
index 000000000..530af804b
--- /dev/null
+++ b/0.18.0/paludis/repositories/portage/xml_things_TEST_setup.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir xml_things_TEST_dir || exit 1
+cd xml_things_TEST_dir || exit 1
+
+cat <<"END" > glsa-123456-78.xml
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet href="/xsl/glsa.xsl" type="text/xsl"?>
+<?xml-stylesheet href="/xsl/guide.xsl" type="text/xsl"?>
+<!DOCTYPE glsa SYSTEM "http://www.gentoo.org/dtd/glsa.dtd">
+
+<glsa id="123456-78">
+ <title>
+ Kittens: Too Adorable
+ </title>
+ <synopsis>
+ Kittens are too adorable. This can lead to excess cuteness.
+ </synopsis>
+ <product type="ebuild">kitten</product>
+ <announced>October 10, 2006</announced>
+ <revised>October 10, 2006: 01</revised>
+ <bug>123456</bug>
+ <access>remote</access>
+ <affected>
+ <package name="animal-feline/kitten" auto="yes" arch="*">
+ <unaffected range="ge">1.23</unaffected>
+ <vulnerable range="lt">1.22</vulnerable>
+ </package>
+ </affected>
+ <background>
+ <p>
+ Kittens are small cats.
+ </p>
+ </background>
+ <description>
+ <p>
+ By being adorable, kittens can get away with too much misbehaviour.
+ </p>
+ </description>
+ <impact type="high">
+ <p>
+ A kitten could get away with going undrowned because of its adorableness.
+ </p>
+ </impact>
+ <workaround>
+ <p>
+ There is no known workaround at this time.
+ </p>
+ </workaround>
+ <resolution>
+ <p>
+ All kitten users should upgrade to the latest version.
+ </p>
+ </resolution>
+ <references>
+ </references>
+</glsa>
+END
+
+cat <<"END" > glsa-987654-32.xml
+<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet href="/xsl/glsa.xsl" type="text/xsl"?>
+<?xml-stylesheet href="/xsl/guide.xsl" type="text/xsl"?>
+<!DOCTYPE glsa SYSTEM "http://www.gentoo.org/dtd/glsa.dtd">
+
+<glsa id="987654-32">
+ <title>
+ Python: Retarded
+ </title>
+ <synopsis>
+ Python is retarded. Reading it can make your eyes bleed.
+ </synopsis>
+ <product type="ebuild">python</product>
+ <announced>October 10, 2006</announced>
+ <revised>October 10, 2006: 01</revised>
+ <bug>987654</bug>
+ <access>remote</access>
+ <affected>
+ <package name="dev-lang/python" auto="yes" arch="x86 sparc mips">
+ <unaffected range="ge">12.34</unaffected>
+ <vulnerable range="lt">12.34</vulnerable>
+ </package>
+ </affected>
+ <background>
+ <p>
+ Python purports to be a programming language.
+ </p>
+ </background>
+ <description>
+ <p>
+ Python abuses whitespace for block structures. This makes anyone reading it
+ suffer severe brain ache.
+ </p>
+ </description>
+ <impact type="high">
+ <p>
+ Anyone reading python code could go crazy.
+ </p>
+ </impact>
+ <workaround>
+ <p>
+ Use a real programming language.
+ </p>
+ </workaround>
+ <resolution>
+ <p>
+ All python users should get their brains examined.
+ </p>
+ </resolution>
+ <references>
+ </references>
+</glsa>
+END
+
diff --git a/0.18.0/paludis/repositories/repository_maker.cc b/0.18.0/paludis/repositories/repository_maker.cc
new file mode 100644
index 000000000..868408b8e
--- /dev/null
+++ b/0.18.0/paludis/repositories/repository_maker.cc
@@ -0,0 +1,151 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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 "repository_maker.hh"
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/system.hh>
+#include <paludis/about.hh>
+#include <list>
+#include <dlfcn.h>
+#include <stdint.h>
+
+#include "config.h"
+
+#ifdef MONOLITHIC
+# include <paludis/repositories/portage/make_ebuild_repository.hh>
+# include <paludis/repositories/vdb/vdb_repository.hh>
+# include <paludis/repositories/virtuals/installed_virtuals_repository.hh>
+# include <paludis/repositories/virtuals/virtuals_repository.hh>
+#endif
+
+using namespace paludis;
+
+PaludisRepositorySoDirNotADirectoryError::PaludisRepositorySoDirNotADirectoryError() throw () :
+ Exception("PALUDIS_REPOSITORY_SO_DIR not a directory")
+{
+}
+
+PaludisRepositorySoDirCannotDlopenError::PaludisRepositorySoDirCannotDlopenError(
+ const std::string & file, const std::string & e) throw () :
+ Exception("Cannot dlopen a repository. so file"),
+ _file(file),
+ _dlerr(e)
+{
+}
+
+PaludisRepositorySoDirCannotDlopenError::~PaludisRepositorySoDirCannotDlopenError() throw ()
+{
+}
+
+const char *
+PaludisRepositorySoDirCannotDlopenError::what() const throw ()
+{
+ if (_what.empty())
+ _what = std::string(Exception::what()) +
+ ": Cannot dlopen repository .so file '" + _file + "': '" + _dlerr + "'";
+ return _what.c_str();
+}
+
+namespace paludis
+{
+ template<>
+ struct Implementation<RepositoryMaker>
+ {
+ std::list<void *> dl_opened;
+ };
+}
+
+void
+RepositoryMaker::load_dir(const FSEntry & so_dir)
+{
+ for (DirIterator d(so_dir), d_end ; d != d_end ; ++d)
+ {
+ if (d->is_directory())
+ load_dir(*d);
+
+ if (! IsFileWithExtension(".so." + stringify(100 * PALUDIS_VERSION_MAJOR +
+ PALUDIS_VERSION_MINOR))(*d))
+ continue;
+
+ /* don't use RTLD_LOCAL, g++ is over happy about template instantiations, and it
+ * can lead to multiple singleton instances. */
+ void * dl(dlopen(stringify(*d).c_str(), RTLD_GLOBAL | RTLD_NOW));
+
+ if (dl)
+ {
+ _imp->dl_opened.push_back(dl);
+
+ void * reg(dlsym(dl, "register_repositories"));
+ if (reg)
+ {
+ reinterpret_cast<void (*)(RepositoryMaker *)>(
+ reinterpret_cast<uintptr_t>(reg))(this);
+ }
+ else
+ throw PaludisRepositorySoDirCannotDlopenError(stringify(*d),
+ "no register_repositories function defined");
+ }
+ else
+ throw PaludisRepositorySoDirCannotDlopenError(stringify(*d), dlerror());
+ }
+
+ if ((so_dir / ".libs").is_directory())
+ load_dir(so_dir / ".libs");
+}
+
+RepositoryMaker::RepositoryMaker() :
+ PrivateImplementationPattern<RepositoryMaker>(new Implementation<RepositoryMaker>)
+{
+#ifdef MONOLITHIC
+
+ register_maker("ebuild", &make_ebuild_repository_wrapped);
+ register_maker("vdb", &VDBRepository::make_vdb_repository);
+ register_maker("virtuals", &VirtualsRepository::make_virtuals_repository);
+ register_maker("installed_virtuals", &InstalledVirtualsRepository::make_installed_virtuals_repository);
+
+#else
+ FSEntry so_dir(getenv_with_default("PALUDIS_REPOSITORY_SO_DIR", LIBDIR "/paludis/repositories"));
+
+ if (! so_dir.is_directory())
+ throw PaludisRepositorySoDirNotADirectoryError();
+
+ load_dir(so_dir);
+
+#endif
+}
+
+RepositoryMaker::~RepositoryMaker()
+{
+}
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker *)
+{
+}
+
+#endif
+
diff --git a/0.18.0/paludis/repositories/repository_maker.hh b/0.18.0/paludis/repositories/repository_maker.hh
new file mode 100644
index 000000000..725e01719
--- /dev/null
+++ b/0.18.0/paludis/repositories/repository_maker.hh
@@ -0,0 +1,92 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_REPOSITORY_MAKER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORY_MAKER_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/virtual_constructor.hh>
+#include <paludis/repository.hh>
+
+namespace paludis
+{
+ class FSEntry;
+
+ /**
+ * Thrown if PALUDIS_REPOSITORY_SO_DIR is not a directory.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grprepository
+ */
+ class PALUDIS_VISIBLE PaludisRepositorySoDirNotADirectoryError :
+ public Exception
+ {
+ public:
+ PaludisRepositorySoDirNotADirectoryError() throw ();
+ };
+
+ /**
+ * Thrown if a repository .so cannot be used.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grprepository
+ */
+ class PaludisRepositorySoDirCannotDlopenError :
+ public Exception
+ {
+ private:
+ std::string _file, _dlerr;
+ mutable std::string _what;
+
+ public:
+ PaludisRepositorySoDirCannotDlopenError(const std::string & file,
+ const std::string & e) throw ();
+
+ ~PaludisRepositorySoDirCannotDlopenError() throw ();
+
+ const char * what() const throw ();
+ };
+
+ /**
+ * Virtual constructor for repositories.
+ *
+ * \ingroup grprepository
+ */
+ class PALUDIS_VISIBLE RepositoryMaker :
+ public VirtualConstructor<std::string,
+ std::tr1::shared_ptr<Repository> (*) (Environment * const,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >),
+ virtual_constructor_not_found::ThrowException<NoSuchRepositoryTypeError> >,
+ public InstantiationPolicy<RepositoryMaker, instantiation_method::SingletonTag>,
+ private PrivateImplementationPattern<RepositoryMaker>
+ {
+ friend class InstantiationPolicy<RepositoryMaker, instantiation_method::SingletonTag>;
+
+ private:
+ RepositoryMaker();
+
+ void load_dir(const FSEntry &);
+
+ public:
+ ~RepositoryMaker();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/vdb/Makefile.am b/0.18.0/paludis/repositories/vdb/Makefile.am
new file mode 100644
index 000000000..e01432f8e
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/Makefile.am
@@ -0,0 +1,90 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = vdb_repository-sr.hh vdb_repository-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludisvdbrepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisvdbrepository.la
+
+endif
+
+libpaludisvdbrepository_la_SOURCES = \
+ vdb_repository.cc \
+ vdb_repository.hh \
+ vdb_version_metadata.hh \
+ vdb_version_metadata.cc \
+ registration.cc
+
+libpaludisvdbrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+paludis_repositories_vdb_includedir = $(includedir)/paludis/repositories/vdb/
+paludis_repositories_vdb_include_HEADERS = \
+ vdb_repository.hh \
+ vdb_version_metadata.hh \
+ vdb_repository-sr.hh
+
+if ! MONOLITHIC
+
+libpaludisvdbrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+TESTS = vdb_repository_TEST
+
+vdb_repository_TEST_SOURCES = vdb_repository_TEST.cc
+
+vdb_repository_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ $(top_builddir)/paludis/environment/test/libpaludistestenvironment.la \
+ libpaludisvdbrepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la
+
+vdb_repository_TEST_CXXFLAGS = -I$(top_srcdir)
+
+EXTRA_DIST = \
+ vdb_repository_TEST.cc \
+ vdb_repository_TEST_setup.sh \
+ vdb_repository_TEST_cleanup.sh \
+ vdb_repository-sr.hh \
+ vdb_repository-sr.cc \
+ vdb_repository.sr
+
+BUILT_SOURCES = \
+ vdb_repository-sr.hh \
+ vdb_repository-sr.cc
+
+check_PROGRAMS = $(TESTS)
+check_SCRIPTS = vdb_repository_TEST_setup.sh vdb_repository_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(top_srcdir)/ebuild/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/test/run_test.sh
+
+vdb_repository-sr.hh : vdb_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/vdb_repository.sr > $@
+
+vdb_repository-sr.cc : vdb_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/vdb_repository.sr > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/0.18.0/paludis/repositories/vdb/registration.cc b/0.18.0/paludis/repositories/vdb/registration.cc
new file mode 100644
index 000000000..95eb9a2fd
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/registration.cc
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 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/vdb/vdb_repository.hh>
+#include "config.h"
+
+using namespace paludis;
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("vdb", &VDBRepository::make_vdb_repository);
+}
+
+#endif
+
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_repository.cc b/0.18.0/paludis/repositories/vdb/vdb_repository.cc
new file mode 100644
index 000000000..4c455de63
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_repository.cc
@@ -0,0 +1,1530 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/vdb/vdb_repository.hh>
+#include <paludis/repositories/vdb/vdb_version_metadata.hh>
+
+#include <paludis/dep_atom.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/ebuild.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/config_file.hh>
+#include <paludis/match_package.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository_name_cache.hh>
+
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fast_unique_copy.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <fstream>
+#include <functional>
+#include <algorithm>
+#include <vector>
+#include <list>
+
+/** \file
+ * Implementation for VDBRepository.
+ *
+ * \ingroup grpvdbrepository
+ */
+
+using namespace paludis;
+
+#include <paludis/repositories/vdb/vdb_repository-sr.cc>
+
+namespace
+{
+ /**
+ * Holds an entry in a VDB.
+ */
+ struct VDBEntry
+ {
+ /// Our package name.
+ QualifiedPackageName name;
+
+ /// Our package version.
+ VersionSpec version;
+
+ /// Our metadata, may be zero.
+ std::tr1::shared_ptr<VDBVersionMetadata> metadata;
+
+ /// Our built USE flags.
+ std::set<UseFlagName> use;
+
+ /// Our installed date.
+ time_t installed_time;
+
+ /// Constructor
+ VDBEntry(const QualifiedPackageName & n, const VersionSpec & v) :
+ name(n),
+ version(v),
+ installed_time(0)
+ {
+ }
+
+ /// Comparison operator
+ bool operator< (const VDBEntry & other) const
+ {
+ if (name < other.name)
+ return true;
+ if (name > other.name)
+ return false;
+ if (version < other.version)
+ return true;
+ return false;
+ }
+
+ /**
+ * Compare a VDBEntry by category only.
+ *
+ * \ingroup grpvdbrepository
+ */
+ struct CompareCategory
+ {
+ bool operator() (const CategoryNamePart & c, const VDBEntry & e) const
+ {
+ return c < e.name.category;
+ }
+
+ bool operator() (const VDBEntry & e, const CategoryNamePart & c) const
+ {
+ return e.name.category < c;
+ }
+
+ bool operator() (const VDBEntry & e, const VDBEntry & c) const
+ {
+ return e.name.category < c.name.category;
+ }
+ };
+
+ /**
+ * Extract category from a VDBEntry.
+ *
+ * \ingroup grpvdbrepository
+ */
+ struct ExtractCategory
+ {
+ CategoryNamePart operator() (const VDBEntry & e) const
+ {
+ return e.name.category;
+ }
+ };
+
+ /**
+ * Extract package from a VDBEntry.
+ *
+ * \ingroup grpvdbrepository
+ */
+ struct ExtractPackage
+ {
+ QualifiedPackageName operator() (const VDBEntry & e) const
+ {
+ return e.name;
+ }
+ };
+
+ /**
+ * Compare a VDBEntry by name only.
+ *
+ * \ingroup grpvdbrepository
+ */
+ struct ComparePackage
+ {
+ bool operator() (const QualifiedPackageName & c, const VDBEntry & e) const
+ {
+ return c < e.name;
+ }
+
+ bool operator() (const VDBEntry & e, const QualifiedPackageName & c) const
+ {
+ return e.name < c;
+ }
+
+ bool operator() (const VDBEntry & e, const VDBEntry & c) const
+ {
+ return e.name < c.name;
+ }
+ };
+
+ /**
+ * Compare a VDBEntry by name and version.
+ *
+ * \ingroup grpvdbrepository
+ */
+ struct CompareVersion
+ {
+ bool operator() (const std::pair<QualifiedPackageName, VersionSpec> & c,
+ const VDBEntry & e) const
+ {
+ if (c.first < e.name)
+ return true;
+ else if (c.first > e.name)
+ return false;
+ else if (c.second < e.version)
+ return true;
+ else
+ return false;
+ }
+
+ bool operator() (const VDBEntry & e,
+ const std::pair<QualifiedPackageName, VersionSpec> & c) const
+ {
+ if (e.name < c.first)
+ return true;
+ else if (e.name > c.first)
+ return false;
+ else if (e.version < c.second)
+ return true;
+ else
+ return false;
+ }
+ };
+ };
+
+ /**
+ * Figure out the format of environment.bz2. If VDB_FORMAT is "paludis-1",
+ * or if there's no VDB_FORMAT and there're no lines with () and no =, it's
+ * an env dump. Otherwise it's a source file.
+ *
+ * \ingroup grpvdbrepository
+ */
+ bool is_full_env(const FSEntry & vdb_dir)
+ {
+ bool result(false);
+
+ if ((vdb_dir / "VDB_FORMAT").is_regular_file())
+ {
+ std::ifstream f(stringify(vdb_dir / "VDB_FORMAT").c_str());
+ if (! f)
+ throw EnvironmentVariableActionError("Could not read '" +
+ stringify(vdb_dir / "VDB_FORMAT") + "'");
+ result = ("paludis-1" != strip_trailing_string(std::string(
+ (std::istreambuf_iterator<char>(f)),
+ std::istreambuf_iterator<char>()), "\n"));
+ }
+ else if (0 == run_command("bunzip2 < " + stringify(vdb_dir / "environment.bz2") +
+ " | grep -q '^[^=]\\+()'"))
+ result = true;
+
+ return result;
+ }
+
+ /**
+ * Figure out whether there's an ebuild present (won't be the case for
+ * virtual things installed using early paludis versions).
+ *
+ * \ingroup grpvdbrepository
+ */
+ bool is_ebuilded(const FSEntry & vdb_dir)
+ {
+ return ! std::count_if(DirIterator(vdb_dir), DirIterator(),
+ IsFileWithExtension(".ebuild"));
+ }
+
+ /**
+ * Fetch the contents of a VDB file.
+ *
+ * \ingroup grpvdbrepository
+ */
+ std::string
+ file_contents(const FSEntry & location, const QualifiedPackageName & name,
+ const VersionSpec & v, const std::string & key)
+ {
+ Context context("When loading VDBRepository entry for '" + stringify(name)
+ + "-" + stringify(v) + "' key '" + key + "' from '" + stringify(location) + "':");
+
+ FSEntry f(location / stringify(name.category) /
+ (stringify(name.package) + "-" + stringify(v)));
+ if (! (f / key).is_regular_file())
+ return "";
+
+ std::ifstream ff(stringify(f / key).c_str());
+ if (! ff)
+ throw VDBRepositoryKeyReadError("Could not read '" + stringify(f / key) + "'");
+ return strip_leading(strip_trailing(std::string((std::istreambuf_iterator<char>(ff)),
+ std::istreambuf_iterator<char>()), " \t\n"), " \t\n");
+ }
+
+ /**
+ * Filter if a USE flag is a -flag.
+ *
+ * \ingroup grpvdbrepository
+ */
+ struct IsPositiveFlag
+ {
+ bool operator() (const std::string & f) const
+ {
+ return 0 != f.compare(0, 1, "-");
+ }
+ };
+}
+
+
+namespace paludis
+{
+ /**
+ * Implementation data for VDBRepository.
+ *
+ * \ingroup grpvdbrepository
+ */
+ template <>
+ struct Implementation<VDBRepository>
+ {
+ VDBRepositoryParams params;
+
+ /// Our owning env.
+ const Environment * const env;
+
+ /// Our base location.
+ FSEntry location;
+
+ /// Root location
+ FSEntry root;
+
+ /// Build root
+ FSEntry buildroot;
+
+ /// World file
+ FSEntry world_file;
+
+ /// Provides cache
+ FSEntry provides_cache;
+
+ /// Do we have entries loaded?
+ mutable bool entries_valid;
+
+ /// Do we have category entries loaded?
+ mutable MakeHashedSet<CategoryNamePart>::Type category_entries_valid;
+
+ /// Our entries, keep this sorted!
+ mutable std::vector<VDBEntry> entries;
+
+ /// Load entries.
+ void load_entries() const;
+ void load_entries_for(const CategoryNamePart &) const;
+
+ /// Load metadata for one entry.
+ void load_entry(std::vector<VDBEntry>::iterator) const;
+
+ /// Provieds data
+ mutable std::tr1::shared_ptr<RepositoryProvidesInterface::ProvidesCollection> provides;
+
+ const FSEntry names_cache_dir;
+
+ std::tr1::shared_ptr<RepositoryNameCache> names_cache;
+
+ /// Constructor.
+ Implementation(const VDBRepository * const, const VDBRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+
+ /// Invalidate.
+ void invalidate() const;
+ };
+
+ Implementation<VDBRepository>::Implementation(const VDBRepository * const r,
+ const VDBRepositoryParams & p) :
+ params(p),
+ env(p.environment),
+ location(p.location),
+ root(p.root),
+ buildroot(p.buildroot),
+ world_file(p.world),
+ provides_cache(p.provides_cache),
+ entries_valid(false),
+ names_cache_dir(p.names_cache),
+ names_cache(new RepositoryNameCache(names_cache_dir, r))
+ {
+ }
+
+ Implementation<VDBRepository>::~Implementation()
+ {
+ }
+
+ void
+ Implementation<VDBRepository>::load_entries() const
+ {
+ Context context("When loading VDBRepository entries from '" +
+ stringify(location) + "':");
+
+ Log::get_instance()->message(ll_debug, lc_context, "VDB load entries started");
+
+ entries.clear();
+ category_entries_valid.clear();
+ entries_valid = true;
+ try
+ {
+ for (DirIterator cat_i(location), cat_iend ; cat_i != cat_iend ; ++cat_i)
+ load_entries_for(CategoryNamePart(cat_i->basename()));
+
+ std::sort(entries.begin(), entries.end());
+ }
+ catch (...)
+ {
+ entries_valid = false;
+ throw;
+ }
+
+ Log::get_instance()->message(ll_debug, lc_context, "VDB load entries done");
+ }
+
+ void
+ Implementation<VDBRepository>::load_entries_for(const CategoryNamePart & cat) const
+ {
+ MakeHashedSet<CategoryNamePart>::Type::const_iterator i(category_entries_valid.find(cat));
+ if (i != category_entries_valid.end())
+ return;
+
+ Context context("When loading VDBRepository entries for '" + stringify(cat) + "' from '" +
+ stringify(location) + "':");
+
+ Log::get_instance()->message(ll_debug, lc_context, "VDB load entries for '" +
+ stringify(cat) + "' started");
+
+ try
+ {
+ category_entries_valid.insert(cat);
+
+ FSEntry dir(location / stringify(cat));
+ if (! dir.is_directory())
+ return;
+
+ for (DirIterator pkg_i(dir), pkg_iend ; pkg_i != pkg_iend ; ++pkg_i)
+ {
+ PackageDepAtom atom("=" + stringify(cat) + "/" + pkg_i->basename());
+ entries.push_back(VDBEntry(atom.package(),
+ atom.version_requirements_ptr()->begin()->version_spec));
+ }
+
+ std::sort(entries.begin(), entries.end());
+ }
+ catch (...)
+ {
+ category_entries_valid.erase(cat);
+ throw;
+ }
+ }
+
+ void
+ Implementation<VDBRepository>::invalidate() const
+ {
+ entries_valid = false;
+ entries.clear();
+ category_entries_valid.clear();
+ }
+
+ void
+ Implementation<VDBRepository>::load_entry(std::vector<VDBEntry>::iterator p) const
+ {
+ Context context("When loading VDBRepository entry for '" + stringify(p->name)
+ + "-" + stringify(p->version) + "' from '" + stringify(location) + "':");
+
+ p->metadata = std::tr1::shared_ptr<VDBVersionMetadata>(new VDBVersionMetadata);
+ p->metadata->build_depend_string = file_contents(location, p->name, p->version, "DEPEND");
+ p->metadata->run_depend_string = file_contents(location, p->name, p->version, "RDEPEND");
+ p->metadata->license_string = file_contents(location, p->name, p->version, "LICENSE");
+ p->metadata->keywords = "*";
+ p->metadata->inherited = file_contents(location, p->name, p->version, "INHERITED");
+ p->metadata->iuse = file_contents(location, p->name, p->version, "IUSE");
+ p->metadata->post_depend_string = file_contents(location, p->name, p->version, "PDEPEND");
+ p->metadata->provide_string = file_contents(location, p->name, p->version, "PROVIDE");
+ p->metadata->src_uri = file_contents(location, p->name, p->version, "SRC_URI");
+ p->metadata->eapi = file_contents(location, p->name, p->version, "EAPI");
+ p->metadata->homepage = file_contents(location, p->name, p->version, "HOMEPAGE");
+ p->metadata->description = file_contents(location, p->name, p->version, "DESCRIPTION");
+
+ std::string slot(file_contents(location, p->name, p->version, "SLOT"));
+ if (slot.empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "VDBRepository entry '" +
+ stringify(p->name) + "-" + stringify(p->version) + "' in '" +
+ stringify(location) + "' has empty SLOT, setting to \"0\"");
+ slot = "0";
+ }
+ p->metadata->slot = SlotName(slot);
+
+ std::string repo(file_contents(location, p->name, p->version, "REPOSITORY"));
+ if (! repo.empty())
+ p->metadata->source.reset(new PackageDatabaseEntry(p->name, p->version,
+ RepositoryName(repo)));
+
+ std::string raw_use(file_contents(location, p->name, p->version, "USE"));
+ p->use.clear();
+ WhitespaceTokeniser::get_instance()->tokenise(raw_use,
+ filter_inserter(create_inserter<UseFlagName>(
+ std::inserter(p->use, p->use.begin())), IsPositiveFlag()));
+ }
+}
+
+VDBRepository::VDBRepository(const VDBRepositoryParams & p) :
+ Repository(RepositoryName("installed"),
+ RepositoryCapabilities::create()
+ .installable_interface(0)
+ .installed_interface(this)
+ .mask_interface(0)
+ .news_interface(0)
+ .sets_interface(this)
+ .syncable_interface(0)
+ .uninstallable_interface(this)
+ .use_interface(this)
+ .world_interface(this)
+ .environment_variable_interface(this)
+ .mirrors_interface(0)
+ .provides_interface(this)
+ .virtuals_interface(0)
+ .destination_interface(this)
+ .config_interface(this)
+ .contents_interface(this),
+ "vdb"),
+ PrivateImplementationPattern<VDBRepository>(new Implementation<VDBRepository>(this, p))
+{
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->location));
+ config_info->add_kv("root", stringify(_imp->root));
+ config_info->add_kv("format", "vdb");
+ config_info->add_kv("world", stringify(_imp->world_file));
+ config_info->add_kv("provides_cache", stringify(_imp->provides_cache));
+ config_info->add_kv("names_cache", stringify(_imp->names_cache_dir));
+ config_info->add_kv("buildroot", stringify(_imp->buildroot));
+
+ _info->add_section(config_info);
+}
+
+VDBRepository::~VDBRepository()
+{
+}
+
+bool
+VDBRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ Context context("When checking for category '" + stringify(c) +
+ "' in " + stringify(name()) + ":");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::pair<std::vector<VDBEntry>::const_iterator, std::vector<VDBEntry>::const_iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), c,
+ VDBEntry::CompareCategory()));
+ return r.first != r.second;
+}
+
+bool
+VDBRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) +
+ "' in " + stringify(name()) + ":");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries_for(q.category);
+
+ std::pair<std::vector<VDBEntry>::const_iterator, std::vector<VDBEntry>::const_iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), q,
+ VDBEntry::ComparePackage()));
+ return r.first != r.second;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+VDBRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+
+#if 0
+ for (std::vector<VDBEntry>::const_iterator c(_imp->entries.begin()), c_end(_imp->entries.end()) ;
+ c != c_end ; ++c)
+ result->insert(c->name.category);
+#else
+ fast_unique_copy(_imp->entries.begin(), _imp->entries.end(),
+ transform_inserter(result->inserter(), VDBEntry::ExtractCategory()),
+ VDBEntry::CompareCategory());
+#endif
+
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+VDBRepository::do_package_names(const CategoryNamePart & c) const
+{
+ /* this isn't particularly fast because it isn't called very often. avoid
+ * changing the data structures used to make this faster at the expense of
+ * slowing down single item queries. */
+
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+
+ std::pair<std::vector<VDBEntry>::const_iterator, std::vector<VDBEntry>::const_iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), c,
+ VDBEntry::CompareCategory()));
+#if 0
+ for ( ; r.first != r.second ; ++(r.first))
+ result->insert(r.first->name);
+#endif
+ fast_unique_copy(r.first, r.second,
+ transform_inserter(result->inserter(), VDBEntry::ExtractPackage()),
+ VDBEntry::ComparePackage());
+
+ return result;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+VDBRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries_for(n.category);
+
+ std::tr1::shared_ptr<VersionSpecCollection> result(new VersionSpecCollection::Concrete);
+
+ std::pair<std::vector<VDBEntry>::const_iterator, std::vector<VDBEntry>::const_iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), n,
+ VDBEntry::ComparePackage()));
+
+ for ( ; r.first != r.second ; ++(r.first))
+ result->insert(r.first->version);
+
+ return result;
+}
+
+bool
+VDBRepository::do_has_version(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When checking for version '" + stringify(v) + "' in '"
+ + stringify(q) + "' in " + stringify(name()) + ":");
+
+ std::tr1::shared_ptr<const VersionSpecCollection> versions(do_version_specs(q));
+ return versions->end() != versions->find(v);
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+VDBRepository::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ Context context("When fetching metadata for '" + stringify(q) +
+ "-" + stringify(v) + "':");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries_for(q.category);
+
+ std::pair<std::vector<VDBEntry>::iterator, std::vector<VDBEntry>::iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), std::make_pair(
+ q, v), VDBEntry::CompareVersion()));
+
+ if (r.first == r.second)
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+ else
+ {
+ if (! r.first->metadata)
+ _imp->load_entry(r.first);
+ return r.first->metadata;
+ }
+}
+
+std::tr1::shared_ptr<const Contents>
+VDBRepository::do_contents(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ Context context("When fetching contents for '" + stringify(q) +
+ "-" + stringify(v) + "':");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::pair<std::vector<VDBEntry>::iterator, std::vector<VDBEntry>::iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), std::make_pair(
+ q, v), VDBEntry::CompareVersion()));
+
+ if (r.first == r.second)
+ {
+ Log::get_instance()->message(ll_warning, lc_context,
+ "version lookup failed for request for '" +
+ stringify(q) + "-" + stringify(v) + "' in repository '" +
+ stringify(name()) + "'");
+ return std::tr1::shared_ptr<const Contents>(new Contents);
+ }
+
+ std::tr1::shared_ptr<Contents> result(new Contents);
+
+ FSEntry f(_imp->location / stringify(q.category) /
+ (stringify(q.package) + "-" + stringify(v)));
+ if (! (f / "CONTENTS").is_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, lc_context,
+ "CONTENTS lookup failed for request for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "'");
+ return result;
+ }
+
+ std::ifstream ff(stringify(f / "CONTENTS").c_str());
+ if (! ff)
+ throw VDBRepositoryKeyReadError("Could not read '" + stringify(f / "CONTENTS") + "'");
+
+ std::string line;
+ unsigned line_number(0);
+ while (std::getline(ff, line))
+ {
+ ++line_number;
+
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(line, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if (tokens.size() < 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ if ("obj" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsMiscEntry(tokens.at(1))));
+ else if ("fif" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsFifoEntry(tokens.at(1))));
+ else if ("dev" == tokens.at(0))
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsDevEntry(tokens.at(1))));
+ else if ("sym" == tokens.at(0))
+ {
+ if (tokens.size() < 4)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken sym line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ result->add(std::tr1::shared_ptr<ContentsEntry>(new ContentsSymEntry(
+ tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return result;
+}
+
+time_t
+VDBRepository::do_installed_time(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When finding installed time for '" + stringify(q) +
+ "-" + stringify(v) + "':");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries_for(q.category);
+
+ std::pair<std::vector<VDBEntry>::iterator, std::vector<VDBEntry>::iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), std::make_pair(
+ q, v), VDBEntry::CompareVersion()));
+
+ if (r.first == r.second)
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+ else
+ {
+ if (0 == r.first->installed_time)
+ {
+ FSEntry f(_imp->location / stringify(q.category) / (stringify(q.package) + "-"
+ + stringify(v)) / "CONTENTS");
+ try
+ {
+ r.first->installed_time = f.ctime();
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Can't get ctime of '"
+ + stringify(f) + "' due to exception '" + e.message() + "' (" + e.what()
+ + ")");
+ r.first->installed_time = 1;
+ }
+ }
+ return r.first->installed_time;
+ }
+}
+
+UseFlagState
+VDBRepository::do_query_use(const UseFlagName & f,
+ const PackageDatabaseEntry * const e) const
+{
+ if (e && e->repository == name())
+ {
+ if (! _imp->entries_valid)
+ _imp->load_entries_for(e->name.category);
+
+ std::pair<std::vector<VDBEntry>::iterator, std::vector<VDBEntry>::iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), std::make_pair(
+ e->name, e->version), VDBEntry::CompareVersion()));
+
+ if (r.first == r.second)
+ return use_unspecified;
+
+ if (!r.first->metadata)
+ _imp->load_entry(r.first);
+
+ if (r.first->use.end() != r.first->use.find(f))
+ return use_enabled;
+ else
+ return use_disabled;
+ }
+ else
+ return use_unspecified;
+}
+
+bool
+VDBRepository::do_query_use_mask(const UseFlagName & u, const PackageDatabaseEntry * e) const
+{
+ return use_disabled == do_query_use(u, e);
+}
+
+bool
+VDBRepository::do_query_use_force(const UseFlagName & u, const PackageDatabaseEntry * e) const
+{
+ return use_enabled == do_query_use(u, e);
+}
+
+std::tr1::shared_ptr<Repository>
+VDBRepository::make_vdb_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") : m->find("repo_file")->second);
+ Context context("When making VDB repository from repo_file '" + repo_file + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw VDBRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string root;
+ if (m->end() == m->find("root") || ((root = m->find("root")->second)).empty())
+ root = "/";
+
+ std::string world;
+ if (m->end() == m->find("world") || ((world = m->find("world")->second)).empty())
+ world = location + "/world";
+
+ std::string provides_cache;
+ if (m->end() == m->find("provides_cache") || ((provides_cache = m->find("provides_cache")->second)).empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The provides_cache key is not set in '"
+ + repo_file + "'. You should read http://paludis.pioto.org/cachefiles.html and select an "
+ "appropriate value.");
+ provides_cache = "/var/empty";
+ }
+
+ std::string names_cache;
+ if (m->end() == m->find("names_cache") || ((names_cache = m->find("names_cache")->second)).empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The names_cache key is not set in '"
+ + repo_file + "'. You should read http://paludis.pioto.org/cachefiles.html and select an "
+ "appropriate value.");
+ names_cache = "/var/empty";
+ }
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = "/var/tmp/paludis";
+
+ return std::tr1::shared_ptr<Repository>(new VDBRepository(VDBRepositoryParams::create()
+ .environment(env)
+ .location(location)
+ .root(root)
+ .world(world)
+ .buildroot(buildroot)
+ .provides_cache(provides_cache)
+ .names_cache(names_cache)));
+}
+
+VDBRepositoryConfigurationError::VDBRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("VDB repository configuration error: " + msg)
+{
+}
+
+VDBRepositoryKeyReadError::VDBRepositoryKeyReadError(
+ const std::string & msg) throw () :
+ ConfigurationError("VDB repository key read error: " + msg)
+{
+}
+
+bool
+VDBRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+VDBRepository::do_uninstall(const QualifiedPackageName & q, const VersionSpec & v, const InstallOptions & o) const
+{
+ Context context("When uninstalling '" + stringify(q) + "-" + stringify(v) +
+ "' from '" + stringify(name()) + "':");
+
+ if (! _imp->root.is_directory())
+ throw PackageInstallActionError("Couldn't uninstall '" + stringify(q) + "-" +
+ stringify(v) + "' because root ('" + stringify(_imp->root) + "') is not a directory");
+
+ std::tr1::shared_ptr<const VersionMetadata> metadata;
+ if (! has_version(q, v))
+ throw PackageInstallActionError("Couldn't uninstall '" + stringify(q) + "-" +
+ stringify(v) + "' because has_version failed");
+ else
+ metadata = version_metadata(q, v);
+
+ PackageDatabaseEntry e(q, v, name());
+
+ std::tr1::shared_ptr<FSEntryCollection> eclassdirs(new FSEntryCollection::Concrete);
+ eclassdirs->append(FSEntry(_imp->location / stringify(q.category) /
+ (stringify(q.package) + "-" + stringify(v))));
+
+ FSEntry pkg_dir(_imp->location / stringify(q.category) /
+ (stringify(q.package) + "-" + stringify(v)));
+
+ std::tr1::shared_ptr<FSEntry> load_env;
+ if (is_full_env(pkg_dir))
+ load_env.reset(new FSEntry(pkg_dir / "environment.bz2"));
+
+ EbuildUninstallCommand uninstall_cmd(EbuildCommandParams::create()
+ .environment(_imp->env)
+ .db_entry(&e)
+ .ebuild_dir(pkg_dir)
+ .files_dir(pkg_dir)
+ .eclassdirs(eclassdirs)
+ .portdir(_imp->location)
+ .distdir(pkg_dir)
+ .buildroot(_imp->buildroot),
+
+ EbuildUninstallCommandParams::create()
+ .root(stringify(_imp->root) + "/")
+ .disable_cfgpro(o.no_config_protect)
+ .unmerge_only(is_ebuilded(pkg_dir))
+ .load_environment(load_env.get()));
+
+ uninstall_cmd();
+}
+
+void
+VDBRepository::do_config(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ Context context("When configuring '" + stringify(q) + "-" + stringify(v) +
+ "' from '" + stringify(name()) + "':");
+
+ if (! _imp->root.is_directory())
+ throw PackageInstallActionError("Couldn't configure '" + stringify(q) + "-" +
+ stringify(v) + "' because root ('" + stringify(_imp->root) + "') is not a directory");
+
+ std::tr1::shared_ptr<const VersionMetadata> metadata;
+ if (! has_version(q, v))
+ throw PackageInstallActionError("Couldn't configure '" + stringify(q) + "-" +
+ stringify(v) + "' because has_version failed");
+ else
+ metadata = version_metadata(q, v);
+
+ PackageDatabaseEntry e(q, v, name());
+
+ std::tr1::shared_ptr<FSEntryCollection> eclassdirs(new FSEntryCollection::Concrete);
+ eclassdirs->append(FSEntry(_imp->location / stringify(q.category) /
+ (stringify(q.package) + "-" + stringify(v))));
+
+ FSEntry pkg_dir(_imp->location / stringify(q.category) /
+ (stringify(q.package) + "-" + stringify(v)));
+
+ std::tr1::shared_ptr<FSEntry> load_env;
+ if (is_full_env(pkg_dir))
+ load_env.reset(new FSEntry(pkg_dir / "environment.bz2"));
+
+ EbuildConfigCommand config_cmd(EbuildCommandParams::create()
+ .environment(_imp->env)
+ .db_entry(&e)
+ .ebuild_dir(pkg_dir)
+ .files_dir(pkg_dir)
+ .eclassdirs(eclassdirs)
+ .portdir(_imp->location)
+ .distdir(pkg_dir)
+ .buildroot(_imp->buildroot),
+
+ EbuildConfigCommandParams::create()
+ .root(stringify(_imp->root) + "/")
+ .load_environment(load_env.get()));
+
+ config_cmd();
+}
+
+std::tr1::shared_ptr<DepAtom>
+VDBRepository::do_package_set(const SetName & s) const
+{
+ Context context("When fetching package set '" + stringify(s) + "' from '" +
+ stringify(name()) + "':");
+
+ if ("everything" == s.data())
+ {
+ std::tr1::shared_ptr<AllDepAtom> result(new AllDepAtom);
+ std::tr1::shared_ptr<GeneralSetDepTag> tag(new GeneralSetDepTag(SetName("everything"), stringify(name())));
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ for (std::vector<VDBEntry>::const_iterator p(_imp->entries.begin()),
+ p_end(_imp->entries.end()) ; p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(p->name));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+
+ return result;
+ }
+ else if ("world" == s.data())
+ {
+ std::tr1::shared_ptr<AllDepAtom> result(new AllDepAtom);
+ std::tr1::shared_ptr<GeneralSetDepTag> tag(new GeneralSetDepTag(SetName("world"), stringify(name())));
+
+ if (_imp->world_file.exists())
+ {
+ LineConfigFile world(_imp->world_file);
+
+ for (LineConfigFile::Iterator line(world.begin()), line_end(world.end()) ;
+ line != line_end ; ++line)
+ {
+ try
+ {
+ if (std::string::npos == line->find('/'))
+ {
+ std::tr1::shared_ptr<DepAtom> atom(_imp->env->package_set(SetName(*line)));
+ if (atom)
+ result->add_child(atom);
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context, "World file '"
+ + stringify(_imp->world_file) + "' entry '" + *line +
+ " is not a known package set");
+ }
+ else
+ {
+ std::tr1::shared_ptr<PackageDepAtom> atom(new PackageDepAtom(QualifiedPackageName(*line)));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+ }
+ catch (const NameError & n)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "World file '"
+ + stringify(_imp->world_file) + "' entry '" + *line + " is broken: '"
+ + n.message() + "' (" + n.what() + ")");
+ }
+ }
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "World file '" + stringify(_imp->world_file) +
+ "' doesn't exist");
+
+ return result;
+ }
+ else
+ return std::tr1::shared_ptr<DepAtom>();
+}
+
+std::tr1::shared_ptr<const SetsCollection>
+VDBRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ std::tr1::shared_ptr<SetsCollection> result(new SetsCollection::Concrete);
+ result->insert(SetName("everything"));
+ result->insert(SetName("world"));
+ return result;
+}
+
+void
+VDBRepository::invalidate()
+{
+ _imp.reset(new Implementation<VDBRepository>(this, _imp->params));
+}
+
+void
+VDBRepository::add_string_to_world(const std::string & n) const
+{
+ Context context("When adding '" + n + "' to world file '" +
+ stringify(_imp->world_file) + "':");
+
+ bool found(false);
+
+ if (_imp->world_file.exists())
+ {
+ LineConfigFile world(_imp->world_file);
+
+ for (LineConfigFile::Iterator line(world.begin()), line_end(world.end()) ;
+ line != line_end ; ++line)
+ if (*line == n)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (! found)
+ {
+ /* portage is retarded, and doesn't ensure that the last entry in world has
+ * a newline character after it. */
+ bool world_file_needs_newline(false);
+ {
+ std::ifstream world(stringify(_imp->world_file).c_str(), std::ios::in);
+ if (world)
+ {
+ world.seekg(0, std::ios::end);
+ if (0 != world.tellg())
+ {
+ world.seekg(-1, std::ios::end);
+ if ('\n' != world.get())
+ world_file_needs_newline = true;
+ }
+ }
+ }
+
+ if (world_file_needs_newline)
+ Log::get_instance()->message(ll_warning, lc_no_context, "World file '"
+ + stringify(_imp->world_file) + "' lacks final newline");
+
+ std::ofstream world(stringify(_imp->world_file).c_str(), std::ios::out | std::ios::app);
+ if (! world)
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot append to world file '"
+ + stringify(_imp->world_file) + "', skipping world update");
+ else
+ {
+ if (world_file_needs_newline)
+ world << std::endl;
+ world << n << std::endl;
+ }
+ }
+}
+
+void
+VDBRepository::remove_string_from_world(const std::string & n) const
+{
+ std::list<std::string> world_lines;
+
+ if (_imp->world_file.exists())
+ {
+ std::ifstream world_file(stringify(_imp->world_file).c_str());
+
+ if (! world_file)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot read world file '"
+ + stringify(_imp->world_file) + "', skipping world update");
+ return;
+ }
+
+ std::string line;
+ while (std::getline(world_file, line))
+ {
+ if (strip_leading(strip_trailing(line, " \t"), "\t") != stringify(n))
+ world_lines.push_back(line);
+ else
+ Log::get_instance()->message(ll_debug, lc_no_context, "Removing line '"
+ + line + "' from world file '" + stringify(_imp->world_file));
+ }
+ }
+
+ std::ofstream world_file(stringify(_imp->world_file).c_str());
+
+ if (! world_file)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot write world file '"
+ + stringify(_imp->world_file) + "', skipping world update");
+ return;
+ }
+
+ std::copy(world_lines.begin(), world_lines.end(),
+ std::ostream_iterator<std::string>(world_file, "\n"));
+}
+
+void
+VDBRepository::add_to_world(const QualifiedPackageName & n) const
+{
+ add_string_to_world(stringify(n));
+}
+
+void
+VDBRepository::add_to_world(const SetName & n) const
+{
+ add_string_to_world(stringify(n));
+}
+
+void
+VDBRepository::remove_from_world(const QualifiedPackageName & n) const
+{
+ remove_string_from_world(stringify(n));
+}
+
+void
+VDBRepository::remove_from_world(const SetName & n) const
+{
+ remove_string_from_world(stringify(n));
+}
+
+std::string
+VDBRepository::get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const
+{
+ Context context("When fetching environment variable '" + var + "' for '" +
+ stringify(for_package) + "':");
+
+ FSEntry vdb_dir(_imp->location / stringify(for_package.name.category)
+ / (stringify(for_package.name.package) + "-" +
+ stringify(for_package.version)));
+
+ if (! vdb_dir.is_directory())
+ throw EnvironmentVariableActionError("Could not find VDB entry for '"
+ + stringify(for_package) + "'");
+
+ if ((vdb_dir / var).is_regular_file())
+ {
+ std::ifstream f(stringify(vdb_dir / var).c_str());
+ if (! f)
+ throw EnvironmentVariableActionError("Could not read '" +
+ stringify(vdb_dir / var) + "'");
+ return strip_trailing_string(
+ std::string((std::istreambuf_iterator<char>(f)),
+ std::istreambuf_iterator<char>()), "\n");
+ }
+ else if ((vdb_dir / "environment.bz2").is_regular_file())
+ {
+ if (is_full_env(vdb_dir))
+ {
+ PStream p("bash -c '( bunzip2 < " + stringify(vdb_dir / "environment.bz2" ) +
+ " ; echo echo \\$" + var + " ) | bash 2>/dev/null'");
+ std::string result(strip_trailing_string(std::string(
+ (std::istreambuf_iterator<char>(p)),
+ std::istreambuf_iterator<char>()), "\n"));
+ if (0 != p.exit_status())
+ throw EnvironmentVariableActionError("Could not load environment.bz2");
+ return result;
+ }
+ else
+ {
+ PStream p("bunzip2 < " + stringify(vdb_dir / "environment.bz2" ));
+ KeyValueConfigFile k(&p);
+
+ if (0 != p.exit_status())
+ throw EnvironmentVariableActionError("Could not get variable '" + var +
+ "' from environment.bz2 for '" + stringify(for_package) + "'");
+
+ return k.get(var);
+ }
+ }
+ else
+ throw EnvironmentVariableActionError("Could not get variable '" + var + "' for '"
+ + stringify(for_package) + "'");
+}
+
+std::tr1::shared_ptr<const RepositoryProvidesInterface::ProvidesCollection>
+VDBRepository::provided_packages() const
+{
+ if (_imp->provides)
+ return _imp->provides;
+
+ if (! load_provided_using_cache())
+ load_provided_the_slow_way();
+
+ return _imp->provides;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+VDBRepository::provided_package_version_metadata(const RepositoryProvidesEntry & p) const
+{
+ std::tr1::shared_ptr<const VersionMetadata> m(version_metadata(p.provided_by_name, p.version));
+ std::tr1::shared_ptr<VDBVirtualVersionMetadata> result(new VDBVirtualVersionMetadata(
+ m->slot, PackageDatabaseEntry(p.provided_by_name, p.version, name())));
+
+ result->eapi = m->eapi;
+ result->build_depend_string = stringify(p.provided_by_name);
+ result->run_depend_string = stringify(p.provided_by_name);
+
+ return result;
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+VDBRepository::do_arch_flags() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+VDBRepository::do_use_expand_flags() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+VDBRepository::do_use_expand_prefixes() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+std::tr1::shared_ptr<const UseFlagNameCollection>
+VDBRepository::do_use_expand_hidden_prefixes() const
+{
+ return std::tr1::shared_ptr<const UseFlagNameCollection>(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagName
+VDBRepository::do_use_expand_name(const UseFlagName & u) const
+{
+ return u;
+}
+
+UseFlagName
+VDBRepository::do_use_expand_value(const UseFlagName & u) const
+{
+ return u;
+}
+
+bool
+VDBRepository::load_provided_using_cache() const
+{
+ if (_imp->provides_cache == FSEntry("/var/empty"))
+ return false;
+
+ Context context("When loading VDB PROVIDEs map using '" + stringify(_imp->provides_cache) + "':");
+
+ std::tr1::shared_ptr<ProvidesCollection> result(new ProvidesCollection::Concrete);
+
+ if (! _imp->provides_cache.is_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Provides cache at '"
+ + stringify(_imp->provides_cache) + "' is not a regular file.");
+ return false;
+ }
+
+ std::ifstream provides_cache(stringify(_imp->provides_cache).c_str());
+
+ std::string version;
+ std::getline(provides_cache, version);
+
+ if (version != "paludis-2")
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Can't use provides cache at '"
+ + stringify(_imp->provides_cache) + "' because format '" + version + "' is not 'paludis-2'");
+ return false;
+ }
+
+ std::string for_name;
+ std::getline(provides_cache, for_name);
+ if (for_name != stringify(name()))
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Can't use provides cache at '"
+ + stringify(_imp->provides_cache) + "' because it was generated for repository '"
+ + for_name + "'. You must not have multiple name caches at the same location.");
+ return false;
+ }
+
+ std::string line;
+ while (std::getline(provides_cache, line))
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(line, std::back_inserter(tokens));
+ if (tokens.size() < 3)
+ continue;
+
+ PackageDatabaseEntry dbe(QualifiedPackageName(tokens.at(0)), VersionSpec(tokens.at(1)), name());
+ DepAtomFlattener f(_imp->env, &dbe, PortageDepParser::parse(
+ join(next(next(tokens.begin())), tokens.end(), " "),
+ PortageDepParserPolicy<PackageDepAtom, false>::get_instance()));
+
+ for (DepAtomFlattener::Iterator p(f.begin()), p_end(f.end()) ; p != p_end ; ++p)
+ result->insert(RepositoryProvidesEntry::create()
+ .virtual_name((*p)->text())
+ .version(dbe.version)
+ .provided_by_name(dbe.name));
+ }
+
+ _imp->provides = result;
+ return true;
+}
+
+void
+VDBRepository::load_provided_the_slow_way() const
+{
+ Context context("When loading VDB PROVIDEs map the slow way:");
+
+ Log::get_instance()->message(ll_debug, lc_no_context, "Starting VDB PROVIDEs map creation");
+
+ std::tr1::shared_ptr<ProvidesCollection> result(new ProvidesCollection::Concrete);
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ for (std::vector<VDBEntry>::iterator e(_imp->entries.begin()),
+ e_end(_imp->entries.end()) ; e != e_end ; ++e)
+ {
+ Context loop_context("When loading VDB PROVIDEs entry for '"
+ + stringify(e->name) + "-" + stringify(e->version) + "':");
+
+ try
+ {
+ std::string provide_str;
+ if (e->metadata)
+ provide_str = e->metadata->ebuild_interface->provide_string;
+ else
+ {
+ // _imp->load_entry(e); slow
+ provide_str = file_contents(_imp->location, e->name, e->version, "PROVIDE");
+ }
+ if (provide_str.empty())
+ continue;
+
+ std::tr1::shared_ptr<const DepAtom> provide(PortageDepParser::parse(provide_str,
+ PortageDepParserPolicy<PackageDepAtom, false>::get_instance()));
+ PackageDatabaseEntry dbe(e->name, e->version, name());
+ DepAtomFlattener f(_imp->env, &dbe, provide);
+
+ for (DepAtomFlattener::Iterator p(f.begin()), p_end(f.end()) ; p != p_end ; ++p)
+ {
+ QualifiedPackageName pp((*p)->text());
+
+ if (pp.category != CategoryNamePart("virtual"))
+ Log::get_instance()->message(ll_warning, lc_no_context, "PROVIDE of non-virtual '"
+ + stringify(pp) + "' from '" + stringify(e->name) + "-"
+ + stringify(e->version) + "' in '" + stringify(name())
+ + "' will not work as expected");
+
+ result->insert(RepositoryProvidesEntry::create()
+ .virtual_name(pp)
+ .version(e->version)
+ .provided_by_name(e->name));
+ }
+ }
+ catch (const InternalError &)
+ {
+ throw;
+ }
+ catch (const Exception & ee)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Skipping VDB PROVIDE entry for '"
+ + stringify(e->name) + "-" + stringify(e->version) + "' due to exception '"
+ + stringify(ee.message()) + "' (" + stringify(ee.what()) + ")");
+ }
+ }
+
+ Log::get_instance()->message(ll_debug, lc_no_context, "Done VDB PROVIDEs map creation");
+
+ _imp->provides = result;
+}
+
+void
+VDBRepository::regenerate_cache() const
+{
+ regenerate_provides_cache();
+ _imp->names_cache->regenerate_cache();
+}
+
+void
+VDBRepository::regenerate_provides_cache() const
+{
+ if (_imp->provides_cache == FSEntry("/var/empty"))
+ return;
+
+ Context context("When generating VDB repository provides cache at '"
+ + stringify(_imp->provides_cache) + "':");
+
+ FSEntry(_imp->provides_cache).unlink();
+ _imp->provides_cache.dirname().mkdir();
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::ofstream f(stringify(_imp->provides_cache).c_str());
+ if (! f)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Cannot write to '"
+ + stringify(_imp->provides_cache) + "'");
+ return;
+ }
+
+ f << "paludis-2" << std::endl;
+ f << name() << std::endl;
+
+ for (std::vector<VDBEntry>::const_iterator c(_imp->entries.begin()), c_end(_imp->entries.end()) ;
+ c != c_end ; ++c)
+ {
+ std::string provide_str;
+ if (c->metadata)
+ provide_str = c->metadata->ebuild_interface->provide_string;
+ else
+ provide_str = file_contents(_imp->location, c->name, c->version, "PROVIDE");
+
+ provide_str = strip_leading(strip_trailing(provide_str, " \t\r\n"), " \t\r\n");
+ if (provide_str.empty())
+ continue;
+
+ f << c->name << " " << c->version << " " << provide_str << std::endl;
+ }
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+VDBRepository::do_category_names_containing_package(const PackageNamePart & p) const
+{
+ if (! _imp->names_cache->usable())
+ return Repository::do_category_names_containing_package(p);
+
+ std::tr1::shared_ptr<const CategoryNamePartCollection> result(
+ _imp->names_cache->category_names_containing_package(p));
+
+ return result ? result : Repository::do_category_names_containing_package(p);
+}
+
+bool
+VDBRepository::is_suitable_destination_for(const PackageDatabaseEntry & e) const
+{
+ return _imp->env->package_database()->fetch_repository(e.repository)->format() == "ebuild";
+}
+
+std::string
+VDBRepository::do_describe_use_flag(const UseFlagName &,
+ const PackageDatabaseEntry * const) const
+{
+ return "";
+}
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_repository.hh b/0.18.0/paludis/repositories/vdb/vdb_repository.hh
new file mode 100644
index 000000000..56a6bd28d
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_repository.hh
@@ -0,0 +1,203 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_VDB_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_VDB_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry.hh>
+
+/** \file
+ * Declarations for VDBRepository.
+ *
+ * \ingroup grpvdbrepository
+ */
+
+namespace paludis
+{
+
+#include <paludis/repositories/vdb/vdb_repository-sr.hh>
+
+ /**
+ * A VDBRepository represents the /var/db/pkg database used for
+ * installed packages.
+ *
+ * It has a stupid name because Portage called it that.
+ *
+ * \ingroup grpvdbrepository
+ */
+ class PALUDIS_VISIBLE VDBRepository :
+ public Repository,
+ public RepositoryInstalledInterface,
+ public RepositoryUseInterface,
+ public RepositoryUninstallableInterface,
+ public RepositorySetsInterface,
+ public RepositoryWorldInterface,
+ public RepositoryEnvironmentVariableInterface,
+ public RepositoryProvidesInterface,
+ public RepositoryDestinationInterface,
+ public RepositoryContentsInterface,
+ public RepositoryConfigInterface,
+ public PrivateImplementationPattern<VDBRepository>
+ {
+ private:
+ bool load_provided_using_cache() const;
+ void load_provided_the_slow_way() const;
+
+ void regenerate_provides_cache() const;
+
+ protected:
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const Contents> do_contents(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual time_t do_installed_time(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_uninstall(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual std::tr1::shared_ptr<DepAtom> do_package_set(const SetName &) const;
+
+ /* RepositoryUseInterface */
+
+ virtual UseFlagState do_query_use(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual bool do_query_use_mask(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual bool do_query_use_force(const UseFlagName &, const PackageDatabaseEntry *) const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_arch_flags() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_flags() const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_hidden_prefixes() const;
+ virtual UseFlagName do_use_expand_name(const UseFlagName & u) const;
+ virtual UseFlagName do_use_expand_value(const UseFlagName & u) const;
+ virtual std::tr1::shared_ptr<const UseFlagNameCollection> do_use_expand_prefixes() const;
+
+ /* end of RepositoryUseInterface */
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names_containing_package(
+ const PackageNamePart &) const;
+
+ virtual void add_string_to_world(const std::string &) const;
+
+ virtual void remove_string_from_world(const std::string &) const;
+
+ virtual void do_config(const QualifiedPackageName &, const VersionSpec &) const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ VDBRepository(const VDBRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static std::tr1::shared_ptr<Repository> make_vdb_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m);
+
+ /**
+ * Destructor.
+ */
+ ~VDBRepository();
+
+ virtual void invalidate();
+
+ virtual void regenerate_cache() const;
+
+ virtual void add_to_world(const QualifiedPackageName &) const;
+
+ virtual void remove_from_world(const QualifiedPackageName &) const;
+
+ virtual void add_to_world(const SetName &) const;
+
+ virtual void remove_from_world(const SetName &) const;
+
+ virtual std::string get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const;
+
+ virtual std::tr1::shared_ptr<const ProvidesCollection> provided_packages() const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> provided_package_version_metadata(
+ const RepositoryProvidesEntry &) const;
+
+ virtual std::tr1::shared_ptr<const SetsCollection> sets_list() const;
+
+ virtual bool is_suitable_destination_for(const PackageDatabaseEntry &) const;
+
+ virtual std::string do_describe_use_flag(const UseFlagName &,
+ const PackageDatabaseEntry * const) const;
+ };
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * PortageRepository::make_portage_repository.
+ *
+ * \ingroup grpvdbrepository
+ * \ingroup grpexceptions
+ */
+ class PALUDIS_VISIBLE VDBRepositoryConfigurationError : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ VDBRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+
+ /**
+ * Thrown if a key read fails.
+ *
+ * \ingroup grpvdbrepository
+ * \ingroup grpexceptions
+ */
+ class PALUDIS_VISIBLE VDBRepositoryKeyReadError : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ VDBRepositoryKeyReadError(const std::string & msg) throw ();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/vdb/vdb_repository.sr b/0.18.0/paludis/repositories/vdb/vdb_repository.sr
new file mode 100644
index 000000000..48df1551a
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_repository.sr
@@ -0,0 +1,26 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_VDBRepositoryParams()
+{
+ key environment "const Environment *"
+ key location FSEntry
+ key root FSEntry
+ key world FSEntry
+ key provides_cache FSEntry
+ key names_cache FSEntry
+ key buildroot FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a VDBRepository
+ *
+ * \see VDBRepository
+ * \ingroup grpvdbrepository
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_repository_TEST.cc b/0.18.0/paludis/repositories/vdb/vdb_repository_TEST.cc
new file mode 100644
index 000000000..c684ee06b
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_repository_TEST.cc
@@ -0,0 +1,249 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/vdb/vdb_repository.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/environment/test/test_environment.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+#include <fstream>
+#include <iterator>
+
+using namespace test;
+using namespace paludis;
+
+/** \file
+ * Test cases for VDBRepository.
+ *
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test VDBRepository repo names
+ *
+ */
+ struct VDBRepositoryRepoNameTest : TestCase
+ {
+ VDBRepositoryRepoNameTest() : TestCase("repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(&env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "installed");
+ }
+ } test_vdb_repository_repo_name;
+
+ /**
+ * \test Test VDBRepository has_category_named
+ *
+ */
+ struct VDBRepositoryHasCategoryNamedTest : TestCase
+ {
+ VDBRepositoryHasCategoryNamedTest() : TestCase("has category named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-one")));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-two")));
+ TEST_CHECK(! repo->has_category_named(CategoryNamePart("cat-three")));
+ }
+ } test_vdb_repository_has_category_named;
+
+ /**
+ * \test Test VDBRepository query_use
+ *
+ */
+ struct VDBRepositoryQueryUseTest : TestCase
+ {
+ VDBRepositoryQueryUseTest() : TestCase("query USE") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+
+ PackageDatabaseEntry e1(CategoryNamePart("cat-one") + PackageNamePart("pkg-one"),
+ VersionSpec("1"), RepositoryName("installed"));
+ PackageDatabaseEntry e2(CategoryNamePart("cat-one") + PackageNamePart("pkg-neither"),
+ VersionSpec("1"), RepositoryName("installed"));
+
+ TEST_CHECK(repo->use_interface->query_use(UseFlagName("flag1"), &e1) == use_enabled);
+ TEST_CHECK(repo->use_interface->query_use(UseFlagName("flag2"), &e1) == use_enabled);
+ TEST_CHECK(repo->use_interface->query_use(UseFlagName("flag3"), &e1) == use_disabled);
+
+ TEST_CHECK(repo->use_interface->query_use(UseFlagName("flag4"), &e2) == use_unspecified);
+ }
+ } test_vdb_repository_query_use;
+
+ /**
+ * \test Test VDBRepository add_to_world.
+ */
+ struct VDBRepositoryAddToWorldNewFileTest : TestCase
+ {
+ VDBRepositoryAddToWorldNewFileTest() : TestCase("add to world (new file)") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-new-file");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+ repo->world_interface->add_to_world(QualifiedPackageName("cat-one/foofoo"));
+ std::ifstream world("vdb_repository_TEST_dir/world-new-file");
+ std::string world_content((std::istreambuf_iterator<char>(world)), std::istreambuf_iterator<char>());
+ TEST_CHECK_EQUAL(world_content, "cat-one/foofoo\n");
+ }
+ } test_vdb_repository_add_to_world_new_file;
+
+ /**
+ * \test Test VDBRepository add_to_world.
+ */
+ struct VDBRepositoryAddToWorldEmptyFileTest : TestCase
+ {
+ VDBRepositoryAddToWorldEmptyFileTest() : TestCase("add to world (empty file)") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-empty");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+ repo->world_interface->add_to_world(QualifiedPackageName("cat-one/foofoo"));
+ std::ifstream world("vdb_repository_TEST_dir/world-empty");
+ std::string world_content((std::istreambuf_iterator<char>(world)), std::istreambuf_iterator<char>());
+ TEST_CHECK_EQUAL(world_content, "cat-one/foofoo\n");
+ }
+ } test_vdb_repository_add_to_world_empty_file;
+
+ /**
+ * \test Test VDBRepository add_to_world.
+ */
+ struct VDBRepositoryAddToWorldNoMatchTest : TestCase
+ {
+ VDBRepositoryAddToWorldNoMatchTest() : TestCase("add to world (no match)") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-no-match");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+ repo->world_interface->add_to_world(QualifiedPackageName("cat-one/foofoo"));
+ std::ifstream world("vdb_repository_TEST_dir/world-no-match");
+ std::string world_content((std::istreambuf_iterator<char>(world)), std::istreambuf_iterator<char>());
+ TEST_CHECK_EQUAL(world_content, "cat-one/foo\ncat-one/bar\ncat-one/oink\ncat-one/foofoo\n");
+ }
+ } test_vdb_repository_add_to_world_no_match;
+
+ /**
+ * \test Test VDBRepository add_to_world.
+ */
+ struct VDBRepositoryAddToWorldMatchTest : TestCase
+ {
+ VDBRepositoryAddToWorldMatchTest() : TestCase("add to world (match)") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-match");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+ repo->world_interface->add_to_world(QualifiedPackageName("cat-one/foofoo"));
+ std::ifstream world("vdb_repository_TEST_dir/world-match");
+ std::string world_content((std::istreambuf_iterator<char>(world)), std::istreambuf_iterator<char>());
+ TEST_CHECK_EQUAL(world_content, "cat-one/foo\ncat-one/foofoo\ncat-one/bar\n");
+ }
+ } test_vdb_repository_add_to_world_match;
+
+ /**
+ * \test Test VDBRepository add_to_world.
+ */
+ struct VDBRepositoryAddToWorldNoMatchNoEOLTest : TestCase
+ {
+ VDBRepositoryAddToWorldNoMatchNoEOLTest() : TestCase("add to world (no match, no trailing eol)") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-no-match-no-eol");
+ std::tr1::shared_ptr<Repository> repo(VDBRepository::make_vdb_repository(
+ &env, keys));
+ repo->world_interface->add_to_world(QualifiedPackageName("cat-one/foofoo"));
+ std::ifstream world("vdb_repository_TEST_dir/world-no-match-no-eol");
+ std::string world_content((std::istreambuf_iterator<char>(world)), std::istreambuf_iterator<char>());
+ TEST_CHECK_EQUAL(world_content, "cat-one/foo\ncat-one/bar\ncat-one/oink\ncat-one/foofoo\n");
+ }
+ } test_vdb_repository_add_to_world_no_match_no_eol;
+}
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh b/0.18.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..e9f03a6b0
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d vdb_repository_TEST_dir ] ; then
+ rm -fr vdb_repository_TEST_dir
+else
+ true
+fi
+
+
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh b/0.18.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh
new file mode 100755
index 000000000..138a6b134
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir -p vdb_repository_TEST_dir || exit 1
+cd vdb_repository_TEST_dir || exit 1
+
+mkdir -p repo1/cat-{one/{pkg-one-1,pkg-both-1},two/{pkg-two-2,pkg-both-2}} || exit 1
+
+for i in SLOT EAPI; do
+ echo "0" >repo1/cat-one/pkg-one-1/${i}
+done
+
+for i in DEPEND RDEPEND LICENSE INHERITED IUSE PDEPEND PROVIDE; do
+ touch repo1/cat-one/pkg-one-1/${i}
+done
+
+echo "flag1 flag2" >>repo1/cat-one/pkg-one-1/USE
+
+touch "world-empty"
+cat <<END > world-no-match
+cat-one/foo
+cat-one/bar
+cat-one/oink
+END
+cat <<END > world-match
+cat-one/foo
+cat-one/foofoo
+cat-one/bar
+END
+cat <<END > world-no-match-no-eol
+cat-one/foo
+cat-one/bar
+END
+echo -n "cat-one/oink" >> world-no-match-no-eol
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_version_metadata.cc b/0.18.0/paludis/repositories/vdb/vdb_version_metadata.cc
new file mode 100644
index 000000000..c5e3171a8
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_version_metadata.cc
@@ -0,0 +1,65 @@
+/* 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 "vdb_version_metadata.hh"
+#include <paludis/portage_dep_parser.hh>
+
+using namespace paludis;
+
+VDBVersionMetadata::VDBVersionMetadata() :
+ VersionMetadata(
+ VersionMetadataBase(SlotName("unset"), "", "", "UNKNOWN"),
+ VersionMetadataCapabilities::create()
+ .deps_interface(this)
+ .origins_interface(this)
+ .ebuild_interface(this)
+ .license_interface(this)
+ .virtual_interface(0)
+ .cran_interface(0)
+ ),
+ VersionMetadataDepsInterface(&PortageDepParser::parse_depend),
+ VersionMetadataLicenseInterface(&PortageDepParser::parse_license)
+{
+}
+
+VDBVersionMetadata::~VDBVersionMetadata()
+{
+}
+
+VDBVirtualVersionMetadata::VDBVirtualVersionMetadata(const SlotName & s,
+ const PackageDatabaseEntry & e) :
+ VersionMetadata(
+ VersionMetadataBase(s, "", "", "UNKNOWN"),
+ VersionMetadataCapabilities::create()
+ .deps_interface(this)
+ .origins_interface(0)
+ .ebuild_interface(0)
+ .license_interface(0)
+ .virtual_interface(this)
+ .cran_interface(0)
+ ),
+ VersionMetadataDepsInterface(&PortageDepParser::parse_depend),
+ VersionMetadataVirtualInterface(e)
+{
+}
+
+VDBVirtualVersionMetadata::~VDBVirtualVersionMetadata()
+{
+}
+
diff --git a/0.18.0/paludis/repositories/vdb/vdb_version_metadata.hh b/0.18.0/paludis/repositories/vdb/vdb_version_metadata.hh
new file mode 100644
index 000000000..f22721bda
--- /dev/null
+++ b/0.18.0/paludis/repositories/vdb/vdb_version_metadata.hh
@@ -0,0 +1,50 @@
+/* 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_VDB_VDB_VERSION_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_VDB_VDB_VERSION_METADATA_HH 1
+
+#include <paludis/version_metadata.hh>
+
+namespace paludis
+{
+ class VDBVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataDepsInterface,
+ public VersionMetadataOriginsInterface,
+ public VersionMetadataEbuildInterface,
+ public VersionMetadataLicenseInterface
+ {
+ public:
+ VDBVersionMetadata();
+ virtual ~VDBVersionMetadata();
+ };
+
+ class VDBVirtualVersionMetadata :
+ public VersionMetadata,
+ public VersionMetadataDepsInterface,
+ public VersionMetadataVirtualInterface
+ {
+ public:
+ VDBVirtualVersionMetadata(const SlotName &, const PackageDatabaseEntry &);
+ virtual ~VDBVirtualVersionMetadata();
+ };
+}
+
+#endif
diff --git a/0.18.0/paludis/repositories/virtuals/Makefile.am b/0.18.0/paludis/repositories/virtuals/Makefile.am
new file mode 100644
index 000000000..afee26556
--- /dev/null
+++ b/0.18.0/paludis/repositories/virtuals/Makefile.am
@@ -0,0 +1,79 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = vr_entry-sr.hh vr_entry-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludisvirtualsrepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludisvirtualsrepository.la
+
+endif
+
+paludis_repositories_virtuals_includedir = $(includedir)/paludis/repositories/virtuals/
+libpaludisvirtualsrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_virtuals_include_HEADERS = \
+ virtuals_repository.hh \
+ installed_virtuals_repository.hh \
+ vr_entry.hh
+
+libpaludisvirtualsrepository_la_SOURCES = \
+ virtuals_repository.cc \
+ installed_virtuals_repository.cc \
+ vr_entry.cc \
+ registration.cc \
+ $(paludis_repositories_portage_include_HEADERS)
+
+if ! MONOLITHIC
+
+libpaludisvirtualsrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+EXTRA_DIST = \
+ vr_entry-sr.hh \
+ vr_entry-sr.cc \
+ vr_entry.sr
+
+BUILT_SOURCES = \
+ vr_entry-sr.hh \
+ vr_entry-sr.cc
+
+TESTS =
+
+check_PROGRAMS = $(TESTS)
+check_SCRIPTS =
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(top_srcdir)/ebuild/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ bash $(top_srcdir)/test/run_test.sh
+
+vr_entry-sr.hh : vr_entry.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/vr_entry.sr > $@
+
+vr_entry-sr.cc : vr_entry.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/vr_entry.sr > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
+
diff --git a/0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.cc b/0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.cc
new file mode 100644
index 000000000..14026207a
--- /dev/null
+++ b/0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.cc
@@ -0,0 +1,297 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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/virtuals/installed_virtuals_repository.hh>
+#include <paludis/repositories/virtuals/vr_entry.hh>
+#include <paludis/util/fast_unique_copy.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/compare.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <vector>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<InstalledVirtualsRepository>
+ {
+ const Environment * const env;
+
+ mutable std::vector<VREntry> entries;
+ mutable bool has_entries;
+
+ Implementation(const Environment * const e) :
+ env(e),
+ has_entries(false)
+ {
+ }
+ };
+
+}
+
+InstalledVirtualsRepository::InstalledVirtualsRepository(const Environment * const env) :
+ Repository(RepositoryName("installed_virtuals"), RepositoryCapabilities::create()
+ .installable_interface(0)
+ .mask_interface(this)
+ .installed_interface(this)
+ .use_interface(0)
+ .news_interface(0)
+ .sets_interface(0)
+ .syncable_interface(0)
+ .uninstallable_interface(this)
+ .mirrors_interface(0)
+ .environment_variable_interface(0)
+ .world_interface(0)
+ .provides_interface(0)
+ .virtuals_interface(0)
+ .contents_interface(0)
+ .config_interface(0)
+ .destination_interface(0),
+ "installed_virtuals"),
+ PrivateImplementationPattern<InstalledVirtualsRepository>(
+ new Implementation<InstalledVirtualsRepository>(env))
+{
+ std::tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+ config_info->add_kv("format", "installed_virtuals");
+ _info->add_section(config_info);
+}
+
+InstalledVirtualsRepository::~InstalledVirtualsRepository()
+{
+}
+
+void
+InstalledVirtualsRepository::need_entries() const
+{
+ if (_imp->has_entries)
+ return;
+
+ /* Populate our _imp->entries. We need to iterate over each repository in
+ * our env's package database, see if it has a provides interface, and if it
+ * does create an entry for each provided package. */
+ for (PackageDatabase::RepositoryIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ; r != r_end ; ++r)
+ {
+ if (! (*r)->provides_interface)
+ continue;
+
+ std::tr1::shared_ptr<const RepositoryProvidesInterface::ProvidesCollection> pp(
+ (*r)->provides_interface->provided_packages());
+
+ for (RepositoryProvidesInterface::ProvidesCollection::Iterator p(
+ pp->begin()), p_end(pp->end()) ; p != p_end ; ++p)
+ {
+ _imp->entries.push_back(VREntry::create()
+ .virtual_name(p->virtual_name)
+ .version(p->version)
+ .provided_by_name(p->provided_by_name)
+ .provided_by_repository((*r)->name()));
+ }
+ }
+
+ /* Our entries must be sorted, for fast lookups. But it's a bit trickier
+ * than a straight operator< comparison, because the same virtual version
+ * can be provided by more than one thing. For ease of coding elsewhere, we
+ * want the 'best' entry to come earlier (sort lower). We define best as
+ * being from the most important repository, and failing that from the
+ * greater provided name (the second part purely for consistency between
+ * invokations). */
+ std::sort(_imp->entries.begin(), _imp->entries.end(),
+ EntriesComparator(_imp->env->package_database()));
+
+ _imp->has_entries = true;
+}
+
+std::tr1::shared_ptr<Repository>
+InstalledVirtualsRepository::make_installed_virtuals_repository(
+ Environment * const env,
+ std::tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >)
+{
+ return std::tr1::shared_ptr<Repository>(new InstalledVirtualsRepository(env));
+}
+
+bool
+InstalledVirtualsRepository::do_query_repository_masks(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+bool
+InstalledVirtualsRepository::do_query_profile_masks(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+std::tr1::shared_ptr<const VersionMetadata>
+InstalledVirtualsRepository::do_version_metadata(
+ const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ need_entries();
+
+ std::pair<std::vector<VREntry>::const_iterator, std::vector<VREntry>::const_iterator> p(
+ std::equal_range(_imp->entries.begin(), _imp->entries.end(),
+ VREntry(q, v, QualifiedPackageName("dummy/package"), RepositoryName("dummy_repository"))));
+
+ if (p.first == p.second)
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+
+ return _imp->env->package_database()->fetch_repository(
+ p.first->provided_by_repository)->provides_interface->provided_package_version_metadata(
+ RepositoryProvidesEntry::create()
+ .virtual_name(p.first->virtual_name)
+ .version(p.first->version)
+ .provided_by_name(p.first->provided_by_name));
+}
+
+bool
+InstalledVirtualsRepository::do_has_version(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ if (q.category.data() != "virtual")
+ return false;
+
+ need_entries();
+
+ std::pair<std::vector<VREntry>::const_iterator, std::vector<VREntry>::const_iterator> p(
+ std::equal_range(_imp->entries.begin(), _imp->entries.end(),
+ VREntry(q, v, QualifiedPackageName("dummy/package"), RepositoryName("dummy_repository"))));
+
+ return p.first != p.second;
+}
+
+std::tr1::shared_ptr<const VersionSpecCollection>
+InstalledVirtualsRepository::do_version_specs(const QualifiedPackageName & q) const
+{
+ if (q.category.data() != "virtual")
+ return std::tr1::shared_ptr<VersionSpecCollection>(new VersionSpecCollection::Concrete);
+
+ need_entries();
+
+ std::pair<std::vector<VREntry>::const_iterator, std::vector<VREntry>::const_iterator> p(
+ std::equal_range(_imp->entries.begin(), _imp->entries.end(),
+ VREntry(q, VersionSpec("0"), QualifiedPackageName("dummy/package"),
+ RepositoryName("dummy_repository")), EntriesNameComparator()));
+
+ std::tr1::shared_ptr<VersionSpecCollection> result(new VersionSpecCollection::Concrete);
+ for ( ; p.first != p.second ; ++p.first)
+ result->insert(p.first->version);
+
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameCollection>
+InstalledVirtualsRepository::do_package_names(const CategoryNamePart & c) const
+{
+ if (c.data() != "virtual")
+ return std::tr1::shared_ptr<QualifiedPackageNameCollection>(new QualifiedPackageNameCollection::Concrete);
+
+ need_entries();
+
+ std::pair<std::vector<VREntry>::const_iterator, std::vector<VREntry>::const_iterator> p(
+ std::equal_range(_imp->entries.begin(), _imp->entries.end(),
+ VREntry(c + PackageNamePart("dummy"), VersionSpec("0"), QualifiedPackageName("dummy/package"),
+ RepositoryName("dummy_repository")), EntriesCategoryComparator()));
+
+
+ std::tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+#if 0
+ /// \todo: in theory, this can be a lot faster
+ for ( ; p.first != p.second ; ++p.first)
+ result->insert(p.first->virtual_name);
+#else
+ fast_unique_copy(p.first, p.second,
+ transform_inserter(result->inserter(), EntriesNameExtractor()),
+ EntriesNameComparator());
+#endif
+
+ return result;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartCollection>
+InstalledVirtualsRepository::do_category_names() const
+{
+ std::tr1::shared_ptr<CategoryNamePartCollection> result(new CategoryNamePartCollection::Concrete);
+ result->insert(CategoryNamePart("virtual"));
+
+#if 0
+ need_entries();
+
+ fast_unique_copy(_imp->entries.begin(), _imp->entries.end(),
+ transform_inserter(result->inserter(), EntriesCategoryExtractor()),
+ EntriesCategoryComparator());
+#endif
+
+ return result;
+}
+
+bool
+InstalledVirtualsRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ if (q.category.data() != "virtual")
+ return false;
+
+ need_entries();
+
+ std::pair<std::vector<VREntry>::const_iterator, std::vector<VREntry>::const_iterator> p(
+ std::equal_range(_imp->entries.begin(), _imp->entries.end(),
+ VREntry(q, VersionSpec("0"), QualifiedPackageName("dummy/package"),
+ RepositoryName("dummy_repository")), EntriesNameComparator()));
+
+ return p.first != p.second;
+}
+
+bool
+InstalledVirtualsRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ if (c.data() != "virtual")
+ return false;
+
+ need_entries();
+
+ std::pair<std::vector<VREntry>::const_iterator, std::vector<VREntry>::const_iterator> p(
+ std::equal_range(_imp->entries.begin(), _imp->entries.end(),
+ VREntry(c + PackageNamePart("dummy"), VersionSpec("0"), QualifiedPackageName("dummy/package"),
+ RepositoryName("dummy_repository")), EntriesCategoryComparator()));
+
+ return p.first != p.second;
+}
+
+bool
+InstalledVirtualsRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+InstalledVirtualsRepository::invalidate()
+{
+ _imp.reset(new Implementation<InstalledVirtualsRepository>(_imp->env));
+}
+
+void
+InstalledVirtualsRepository::do_uninstall(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const
+{
+}
+
diff --git a/0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.hh b/0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.hh
new file mode 100644
index 000000000..75a5fa0cb
--- /dev/null
+++ b/0.18.0/paludis/repositories/virtuals/installed_virtuals_repository.hh
@@ -0,0 +1,99 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 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_VIRTUALS_INSTALLED_VIRTUALS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_VIRTUALS_INSTALLED_VIRTUALS_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+
+namespace paludis
+{
+ /**
+ * Repository representing installed virtual packages.
+ *
+ * \ingroup grpvirtualsrepository
+ */
+ class PALUDIS_VISIBLE InstalledVirtualsRepository :
+ public Repository,
+ public RepositoryInstalledInterface,
+ public RepositoryUninstallableInterface,
+ public RepositoryMaskInterface,
+ private PrivateImplementationPattern<InstalledVirtualsRepository>
+ {
+ private:
+ void need_entries() const;
+
+ protected:
+ virtual bool do_query_repository_masks(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_query_profile_masks(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionMetadata> do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::tr1::shared_ptr<const VersionSpecCollection> do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameCollection> do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartCollection> do_category_names() const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_uninstall(const QualifiedPackageName &, const VersionSpec &,
+