aboutsummaryrefslogtreecommitdiff
path: root/0.8.0/paludis/repositories
diff options
context:
space:
mode:
Diffstat (limited to '0.8.0/paludis/repositories')
-rw-r--r--0.8.0/paludis/repositories/Makefile.am5
-rw-r--r--0.8.0/paludis/repositories/cran/Makefile.am97
-rw-r--r--0.8.0/paludis/repositories/cran/cran_dep_parser.cc61
-rw-r--r--0.8.0/paludis/repositories/cran/cran_dep_parser.hh21
-rw-r--r--0.8.0/paludis/repositories/cran/cran_dep_parser_TEST.cc149
-rw-r--r--0.8.0/paludis/repositories/cran/cran_description.cc103
-rw-r--r--0.8.0/paludis/repositories/cran/cran_description.hh129
-rw-r--r--0.8.0/paludis/repositories/cran/cran_installed_repository.cc599
-rw-r--r--0.8.0/paludis/repositories/cran/cran_installed_repository.hh137
-rw-r--r--0.8.0/paludis/repositories/cran/cran_installed_repository.sr23
-rw-r--r--0.8.0/paludis/repositories/cran/cran_repository.cc637
-rw-r--r--0.8.0/paludis/repositories/cran/cran_repository.hh137
-rw-r--r--0.8.0/paludis/repositories/cran/cran_repository.sr27
-rw-r--r--0.8.0/paludis/repositories/cran/cran_repository_TEST.cc97
-rwxr-xr-x0.8.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh8
-rwxr-xr-x0.8.0/paludis/repositories/cran/cran_repository_TEST_setup.sh57
-rw-r--r--0.8.0/paludis/repositories/fake/Makefile.am31
-rw-r--r--0.8.0/paludis/repositories/fake/fake_installed_repository.cc49
-rw-r--r--0.8.0/paludis/repositories/fake/fake_installed_repository.hh41
-rw-r--r--0.8.0/paludis/repositories/fake/fake_repository.cc47
-rw-r--r--0.8.0/paludis/repositories/fake/fake_repository.hh40
-rw-r--r--0.8.0/paludis/repositories/fake/fake_repository_base.cc258
-rw-r--r--0.8.0/paludis/repositories/fake/fake_repository_base.hh146
-rw-r--r--0.8.0/paludis/repositories/nothing/Makefile.am40
-rw-r--r--0.8.0/paludis/repositories/nothing/nothing_repository.cc256
-rw-r--r--0.8.0/paludis/repositories/nothing/nothing_repository.hh116
-rw-r--r--0.8.0/paludis/repositories/nothing/nothing_repository.sr23
-rw-r--r--0.8.0/paludis/repositories/portage/Makefile.am127
-rw-r--r--0.8.0/paludis/repositories/portage/glsa.cc233
-rw-r--r--0.8.0/paludis/repositories/portage/glsa.hh97
-rw-r--r--0.8.0/paludis/repositories/portage/glsa.sr8
-rw-r--r--0.8.0/paludis/repositories/portage/make_ebin_repository.cc114
-rw-r--r--0.8.0/paludis/repositories/portage/make_ebin_repository.hh35
-rw-r--r--0.8.0/paludis/repositories/portage/make_ebuild_repository.cc159
-rw-r--r--0.8.0/paludis/repositories/portage/make_ebuild_repository.hh38
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository.cc1004
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository.hh166
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_TEST.cc666
-rwxr-xr-x0.8.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh10
-rwxr-xr-x0.8.0/paludis/repositories/portage/portage_repository_TEST_setup.sh226
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.cc379
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.hh71
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.cc556
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.hh70
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_entries.cc38
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_entries.hh126
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_entry.cc32
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_exceptions.cc29
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_exceptions.hh53
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_news.cc284
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_news.hh134
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_params.cc8
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_params.hh42
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_params.sr34
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_profile.cc686
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_profile.hh125
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_profile_file.cc81
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_profile_file.hh45
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_sets.cc379
-rw-r--r--0.8.0/paludis/repositories/portage/portage_repository_sets.hh80
-rw-r--r--0.8.0/paludis/repositories/portage/xml_things.cc188
-rw-r--r--0.8.0/paludis/repositories/portage/xml_things_TEST.cc92
-rwxr-xr-x0.8.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh11
-rwxr-xr-x0.8.0/paludis/repositories/portage/xml_things_TEST_setup.sh115
-rw-r--r--0.8.0/paludis/repositories/vdb/Makefile.am66
-rw-r--r--0.8.0/paludis/repositories/vdb/vdb_repository.cc1179
-rw-r--r--0.8.0/paludis/repositories/vdb/vdb_repository.hh174
-rw-r--r--0.8.0/paludis/repositories/vdb/vdb_repository.sr24
-rw-r--r--0.8.0/paludis/repositories/vdb/vdb_repository_TEST.cc238
-rwxr-xr-x0.8.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh11
-rwxr-xr-x0.8.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh35
-rw-r--r--0.8.0/paludis/repositories/virtuals/Makefile.am61
-rw-r--r--0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.cc322
-rw-r--r--0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.hh91
-rw-r--r--0.8.0/paludis/repositories/virtuals/virtuals_repository.cc338
-rw-r--r--0.8.0/paludis/repositories/virtuals/virtuals_repository.hh87
-rw-r--r--0.8.0/paludis/repositories/virtuals/vr_entry.cc26
-rw-r--r--0.8.0/paludis/repositories/virtuals/vr_entry.hh119
-rw-r--r--0.8.0/paludis/repositories/virtuals/vr_entry.sr16
79 files changed, 12662 insertions, 0 deletions
diff --git a/0.8.0/paludis/repositories/Makefile.am b/0.8.0/paludis/repositories/Makefile.am
new file mode 100644
index 0000000..69fc8a5
--- /dev/null
+++ b/0.8.0/paludis/repositories/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = cran fake nothing portage vdb virtuals
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/0.8.0/paludis/repositories/cran/Makefile.am b/0.8.0/paludis/repositories/cran/Makefile.am
new file mode 100644
index 0000000..cb681c0
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/Makefile.am
@@ -0,0 +1,97 @@
+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
+paludis_repositories_lib_LTLIBRARIES = libpaludiscranrepository.la
+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_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_description.cc \
+ cran_dep_parser.cc \
+ cran_repository.cc \
+ cran_installed_repository.cc \
+ $(paludis_repositories_cran_include_HEADERS)
+
+libpaludiscranrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+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 > $@
+
diff --git a/0.8.0/paludis/repositories/cran/cran_dep_parser.cc b/0.8.0/paludis/repositories/cran/cran_dep_parser.cc
new file mode 100644
index 0000000..456487e
--- /dev/null
+++ b/0.8.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;
+
+DepAtom::ConstPointer
+CRANDepParser::parse(const std::string & s)
+{
+ Context context("When parsing CRAN 'Depends:' string: '" + s + "':");
+
+ CompositeDepAtom::Pointer 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;
+ PackageDepAtom::Pointer atom(new PackageDepAtom(atom_string));
+ result->add_child(atom);
+ }
+
+ return result;
+}
diff --git a/0.8.0/paludis/repositories/cran/cran_dep_parser.hh b/0.8.0/paludis/repositories/cran/cran_dep_parser.hh
new file mode 100644
index 0000000..69bdd80
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_dep_parser.hh
@@ -0,0 +1,21 @@
+#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
+ {
+ static DepAtom::ConstPointer parse(const std::string & s);
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/cran/cran_dep_parser_TEST.cc b/0.8.0/paludis/repositories/cran/cran_dep_parser_TEST.cc
new file mode 100644
index 0000000..9308c8d
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_dep_parser_TEST.cc
@@ -0,0 +1,149 @@
+/* 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/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;
+
+#ifndef DOXYGEN
+namespace
+{
+ class DepAtomDumper :
+ public DepAtomVisitorTypes::ConstVisitor,
+ private InstantiationPolicy<DepAtomDumper, instantiation_method::NonCopyableTag>
+ {
+ private:
+ std::ostream * const _o;
+
+ public:
+ DepAtomDumper(std::ostream * const o);
+
+ void visit(const AllDepAtom * const);
+
+ void visit(const AnyDepAtom * const);
+
+ void visit(const UseDepAtom * const);
+
+ void visit(const PackageDepAtom * const);
+
+ void visit(const PlainTextDepAtom * const);
+
+ void visit(const BlockDepAtom * const);
+ };
+
+ DepAtomDumper::DepAtomDumper(std::ostream * const o) :
+ _o(o)
+ {
+ }
+
+ void
+ DepAtomDumper::visit(const AllDepAtom * const a)
+ {
+ *_o << "<all>";
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+ *_o << "</all>";
+ }
+
+ void
+ DepAtomDumper::visit(const AnyDepAtom * const a)
+ {
+ *_o << "<any>";
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+ *_o << "</any>";
+ }
+
+ void
+ DepAtomDumper::visit(const UseDepAtom * const a)
+ {
+ *_o << "<use flag=\"" << a->flag() << "\" inverse=\""
+ << (a->inverse() ? "true" : "false") << "\">";
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+ *_o << "</use>";
+ }
+
+ void
+ DepAtomDumper::visit(const PackageDepAtom * const p)
+ {
+ *_o << "<package";
+ if (p->slot_ptr())
+ *_o << " slot=\"" << *p->slot_ptr() << "\"";
+ if (p->version_spec_ptr())
+ *_o << " version=\"" << p->version_operator() << *p->version_spec_ptr() << "\"";
+ *_o << ">" << p->package() << "</package>";
+ }
+
+ void
+ DepAtomDumper::visit(const PlainTextDepAtom * const t)
+ {
+ *_o << "<text>" << t->text() << "</text>";
+ }
+
+ void
+ DepAtomDumper::visit(const BlockDepAtom * const b)
+ {
+ *_o << "<block>";
+ b->blocked_atom()->accept(this);
+ *_o << "</block>";
+ }
+}
+#endif
+
+/** \file
+ * Test cases for CRANRepository.
+ *
+ * \ingroup grptestcases
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test CRANDepParser::parse to parse well formed CRAN Depends: strings.
+ *
+ * \ingroup grptestcases
+ */
+ struct CRANDepParserTest : TestCase
+ {
+ CRANDepParserTest() : TestCase("DepParser") { }
+
+ void run()
+ {
+ std::stringstream s1, s2, s3;
+ DepAtomDumper d1(&s1), d2(&s2), d3(&s3);
+ // test R dependency
+ std::string dep1("R (>= 2.0.0)");
+ CRANDepParser::parse(dep1)->accept(&d1);
+ TEST_CHECK_EQUAL(s1.str(), "<all><package version=\">=2.0.0\">dev-lang/R</package></all>");
+ // test varying whitespaces
+ std::string dep2("testpackage1 \t(<1.9)");
+ CRANDepParser::parse(dep2)->accept(&d2);
+ TEST_CHECK_EQUAL(s2.str(), "<all><package version=\"<1.9\">cran/testpackage1</package></all>");
+ // test for package-name and version normalisation
+ std::string dep3("R.matlab (>= 2.3-1)");
+ CRANDepParser::parse(dep3)->accept(&d3);
+ TEST_CHECK_EQUAL(s3.str(), "<all><package version=\">=2.3.1\">cran/R-matlab</package></all>");
+ }
+ } test_cran_dep_parser;
+}
diff --git a/0.8.0/paludis/repositories/cran/cran_description.cc b/0.8.0/paludis/repositories/cran/cran_description.cc
new file mode 100644
index 0000000..b831414
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_description.cc
@@ -0,0 +1,103 @@
+/* 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/repositories/cran/cran_description.hh>
+#include <paludis/repositories/cran/cran_dep_parser.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) :
+ name("cran/" + n),
+ version("0"),
+ metadata(new VersionMetadata::CRAN(CRANDepParser::parse))
+{
+ Context context("When parsing file '" + stringify(f) + "' for package '" + n + "':");
+
+ if (! f.is_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Unexpected irregular file: '" + stringify(f) + "'.");
+ metadata->eapi = "INVALID";
+
+ return;
+ }
+
+ LineConfigFile file(f);
+ LineConfigFile::Iterator l(file.begin()), l_end(file.end());
+
+ // Fill in default values
+ metadata->slot = SlotName("0");
+ metadata->eapi = "CRAN-0";
+ metadata->get_cran_interface()->keywords = std::string("*");
+
+ 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)
+ {
+ metadata->get_cran_interface()->package = value;
+ metadata->homepage = "http://cran.r-project.org/src/contrib/Descriptions/" + value + ".html";
+ 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 if ("Bundle" == key)
+ {
+ metadata->get_cran_interface()->is_bundle = true;
+ }
+ else if ("Version" == key)
+ {
+ metadata->get_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.build_depend_string = value;
+ metadata->deps.run_depend_string = value;
+ }
+ }
+}
+
diff --git a/0.8.0/paludis/repositories/cran/cran_description.hh b/0.8.0/paludis/repositories/cran/cran_description.hh
new file mode 100644
index 0000000..45f354e
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_description.hh
@@ -0,0 +1,129 @@
+/* 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_DESCRIPTION_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_DESCRIPTION_HH 1
+
+#include <paludis/version_metadata.hh>
+#include <paludis/util/fs_entry.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.
+ VersionMetadata::Pointer metadata;
+
+ /// 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);
+
+ /// 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
+ {
+ 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
+ {
+ 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.8.0/paludis/repositories/cran/cran_installed_repository.cc b/0.8.0/paludis/repositories/cran/cran_installed_repository.cc
new file mode 100644
index 0000000..a34a1c8
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_installed_repository.cc
@@ -0,0 +1,599 @@
+/* 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/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/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>, VersionMetadata::Pointer>::Type MetadataMap;
+
+ template <>
+ struct Implementation<CRANInstalledRepository> :
+ InternalCounted<Implementation<CRANInstalledRepository> >
+ {
+ /// Our owning db..
+ const PackageDatabase * const db;
+
+ /// 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;
+
+ /// Load metadata for one entry.
+ void load_entry(std::vector<CRANDescription>::iterator) const;
+
+ /// Metadata cache
+ mutable MetadataMap metadata;
+
+ /// Provide map.
+ mutable std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Constructor.
+ Implementation(const CRANInstalledRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+
+ /// Invalidate.
+ void invalidate() const;
+ };
+}
+
+Implementation<CRANInstalledRepository>::Implementation(const CRANInstalledRepositoryParams & p) :
+ db(p.package_database),
+ 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);
+ 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;
+ }
+}
+
+void
+Implementation<CRANInstalledRepository>::invalidate() const
+{
+ entries_valid = false;
+ entries.clear();
+}
+
+CRANInstalledRepository::CRANInstalledRepository(const CRANInstalledRepositoryParams & p) :
+ Repository(RepositoryName("cran_installed"),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(0)
+ .installed_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)),
+ PrivateImplementationPattern<CRANInstalledRepository>(new Implementation<CRANInstalledRepository>(p))
+{
+ RepositoryInfoSection::Pointer 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;
+}
+
+CategoryNamePartCollection::ConstPointer
+CRANInstalledRepository::do_category_names() const
+{
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ CategoryNamePartCollection::Pointer result(new CategoryNamePartCollection::Concrete);
+ result->insert(CategoryNamePart("cran"));
+ return result;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+CRANInstalledRepository::do_package_names(const CategoryNamePart & c) const
+{
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ QualifiedPackageNameCollection::Pointer 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;
+}
+
+VersionSpecCollection::ConstPointer
+CRANInstalledRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ VersionSpecCollection::Pointer result(new VersionSpecCollection::Concrete);
+
+ std::pair<std::vector<CRANDescription>::const_iterator, std::vector<CRANDescription>::const_iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), n,
+ CRANDescription::ComparePackage()));
+
+ for ( ; r.first != r.second ; ++(r.first))
+ result->insert(r.first->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()) + ":");
+
+ VersionSpecCollection::ConstPointer versions(do_version_specs(q));
+ return versions->end() != versions->find(v);
+}
+
+VersionMetadata::ConstPointer
+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())));
+
+ VersionMetadata::Pointer result(0);
+
+ FSEntry d(_imp->location);
+ d /= stringify(q.package);
+ d /= "DESCRIPTION";
+
+ if (d.is_regular_file())
+ {
+ CRANDescription description(stringify(q.package), d);
+ 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.assign(new VersionMetadata(CRANDepParser::parse));
+ result->eapi = "UNKNOWN";
+ return result;
+ }
+
+ _imp->metadata.insert(std::make_pair(std::make_pair(q, v), result));
+ return result;
+}
+
+Contents::ConstPointer
+CRANInstalledRepository::do_contents(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ Context context("When fetching contents for " + stringify(q) +
+ "-" + stringify(v));
+
+ Contents::Pointer 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(ContentsEntry::Pointer(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(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(ContentsEntry::Pointer(new ContentsSymEntry(
+ tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return result;
+}
+
+CountedPtr<Repository>
+CRANInstalledRepository::make_cran_installed_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer 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 CountedPtr<Repository>(new CRANInstalledRepository(CRANInstalledRepositoryParams::create()
+ .environment(env)
+ .package_database(db)
+ .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");
+
+ VersionMetadata::ConstPointer vm(do_version_metadata(q, v));
+
+ MakeEnvCommand cmd(LIBEXECDIR "/paludis/cran.bash unmerge", "");
+ cmd = cmd("PN", vm->get_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) + "'");
+}
+
+DepAtom::Pointer
+CRANInstalledRepository::do_package_set(const std::string & s) const
+{
+ Context context("When fetching package set '" + s + "' from '" +
+ stringify(name()) + "':");
+
+ if ("everything" == s)
+ {
+ AllDepAtom::Pointer 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)
+ {
+ PackageDepAtom::Pointer atom(new PackageDepAtom(p->name));
+ result->add_child(atom);
+ }
+
+ return result;
+ }
+ else if ("world" == s)
+ {
+ AllDepAtom::Pointer 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)
+ {
+ PackageDepAtom::Pointer atom(new PackageDepAtom(QualifiedPackageName(*line)));
+ result->add_child(atom);
+ }
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context, "World file '" + stringify(_imp->world_file)
+ + "' doesn't exist");
+
+ return result;
+ }
+ else
+ return DepAtom::Pointer(0);
+}
+
+SetsCollection::ConstPointer
+CRANInstalledRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ SetsCollection::Pointer result(new SetsCollection::Concrete);
+ result->insert("everything");
+ result->insert("world");
+ return result;
+}
+
+bool
+CRANInstalledRepository::do_sync() const
+{
+ return false;
+}
+
+void
+CRANInstalledRepository::invalidate() const
+{
+ _imp->invalidate();
+}
+
+void
+CRANInstalledRepository::add_to_world(const QualifiedPackageName & 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 (QualifiedPackageName(*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_from_world(const QualifiedPackageName & 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_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"));
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_cran_installed_repository PALUDIS_ATTRIBUTE((used)) (
+ "cran_installed", &CRANInstalledRepository::make_cran_installed_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/cran/cran_installed_repository.hh b/0.8.0/paludis/repositories/cran/cran_installed_repository.hh
new file mode 100644
index 0000000..6f82e17
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_installed_repository.hh
@@ -0,0 +1,137 @@
+/* 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 RepositoryUninstallableInterface,
+ public RepositorySetsInterface,
+ public RepositoryWorldInterface,
+ public PrivateImplementationPattern<CRANInstalledRepository>
+ {
+ protected:
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual CategoryNamePartCollection::ConstPointer do_category_names() const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual VersionMetadata::ConstPointer do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual Contents::ConstPointer do_contents(
+ 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 DepAtom::Pointer do_package_set(const std::string &) const;
+
+ virtual SetsCollection::ConstPointer sets_list() const;
+
+ virtual bool do_sync() const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ CRANInstalledRepository(const CRANInstalledRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static CountedPtr<Repository> make_cran_installed_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer m);
+
+ /**
+ * Destructor.
+ */
+ ~CRANInstalledRepository();
+
+ virtual bool installed() const
+ {
+ return true;
+ }
+
+ virtual void invalidate() const;
+
+ virtual void add_to_world(const QualifiedPackageName &) const;
+
+ virtual void remove_from_world(const QualifiedPackageName &) 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.8.0/paludis/repositories/cran/cran_installed_repository.sr b/0.8.0/paludis/repositories/cran/cran_installed_repository.sr
new file mode 100644
index 0000000..48791bc
--- /dev/null
+++ b/0.8.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 package_database "const PackageDatabase *"
+ key location FSEntry
+ key root FSEntry
+ key world FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a CRANInstalledRepository
+ *
+ * \see CRANInstalledRepository
+ * \ingroup grpcraninstrepository
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.8.0/paludis/repositories/cran/cran_repository.cc b/0.8.0/paludis/repositories/cran/cran_repository.cc
new file mode 100644
index 0000000..7ab4ac2
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_repository.cc
@@ -0,0 +1,637 @@
+/* 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 "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/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>, VersionMetadata::Pointer>::Type MetadataMap;
+
+ /**
+ * Implementation data for a CRANRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+ template <>
+ struct Implementation<CRANRepository> :
+ InternalCounted<Implementation<CRANRepository> >
+ {
+ /// Our owning db.
+ const PackageDatabase * const db;
+
+ /// 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();
+
+ /// Invalidate our cache.
+ void invalidate() const;
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+ };
+}
+
+Implementation<CRANRepository>::Implementation(const CRANRepositoryParams & p) :
+ db(p.package_database),
+ 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()
+{
+}
+
+void
+Implementation<CRANRepository>::invalidate() const
+{
+ package_names.clear();
+ has_packages = false;
+ version_specs.clear();
+ metadata.clear();
+ has_mirrors = false;
+ mirrors.clear();
+}
+
+
+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)
+ .virtuals_interface(0)),
+ PrivateImplementationPattern<CRANRepository>(new Implementation<CRANRepository>(p))
+{
+ RepositoryInfoSection::Pointer 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);
+}
+
+CategoryNamePartCollection::ConstPointer
+CRANRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+
+ CategoryNamePartCollection::Pointer result(new CategoryNamePartCollection::Concrete);
+ result->insert(CategoryNamePart("cran"));
+
+ return result;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+CRANRepository::do_package_names(const CategoryNamePart & c) const
+{
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ need_packages();
+
+ QualifiedPackageNameCollection::Pointer 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;
+}
+
+VersionSpecCollection::ConstPointer
+CRANRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ need_packages();
+
+ VersionSpecCollection::Pointer 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")));
+
+ std::string dep(d.metadata->deps.build_depend_string);
+ std::string pkg(d.metadata->get_cran_interface()->package);
+ if ("" == dep)
+ dep = pkg;
+ else
+ dep += "," + pkg;
+ d.metadata->deps.build_depend_string = dep;
+
+ _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);
+}
+
+VersionMetadata::ConstPointer
+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())));
+
+ VersionMetadata::Pointer result(new VersionMetadata(CRANDepParser::parse));
+
+ 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);
+ 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.assign(new VersionMetadata(CRANDepParser::parse));
+ result->eapi = "UNKNOWN";
+ }
+
+ _imp->metadata.insert(std::make_pair(std::make_pair(q, v), result));
+ return result;
+}
+
+Contents::ConstPointer
+CRANRepository::do_contents(
+ const CategoryNamePart &, const PackageNamePart &, const VersionSpec &) const
+{
+ return Contents::Pointer(new Contents);
+}
+
+CountedPtr<Repository>
+CRANRepository::make_cran_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer 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 CountedPtr<Repository>(new CRANRepository(CRANRepositoryParams::create()
+ .environment(env)
+ .package_database(db)
+ .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");
+ VersionMetadata::ConstPointer vm(do_version_metadata(q, vn));
+ std::string p(vm->get_cran_interface()->package);
+ std::string v(vm->get_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("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);
+
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't merge '" + stringify(q) + "-" + stringify(vn) + "' to '" +
+ stringify(_imp->root) + "'");
+
+ return;
+}
+
+DepAtom::Pointer
+CRANRepository::do_package_set(const std::string & s) const
+{
+ if ("base" == s)
+ {
+ /**
+ * \todo Implement system as all package which are installed
+ * by dev-lang/R by default.
+ */
+ return AllDepAtom::Pointer(new AllDepAtom);
+ }
+ else
+ return DepAtom::Pointer(0);
+}
+
+SetsCollection::ConstPointer
+CRANRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ SetsCollection::Pointer result(new SetsCollection::Concrete);
+ result->insert("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() const
+{
+ _imp->invalidate();
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_cran_repository PALUDIS_ATTRIBUTE((used)) (
+ "cran", &CRANRepository::make_cran_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/cran/cran_repository.hh b/0.8.0/paludis/repositories/cran/cran_repository.hh
new file mode 100644
index 0000000..fcaf61b
--- /dev/null
+++ b/0.8.0/paludis/repositories/cran/cran_repository.hh
@@ -0,0 +1,137 @@
+/* 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 CategoryNamePartCollection::ConstPointer do_category_names() const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual VersionMetadata::ConstPointer do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual Contents::ConstPointer do_contents(
+ const CategoryNamePart &, const PackageNamePart &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ virtual DepAtom::Pointer do_package_set(const std::string &) const;
+
+ virtual SetsCollection::ConstPointer sets_list() const;
+
+ virtual bool do_sync() const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ CRANRepository(const CRANRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static CountedPtr<Repository> make_cran_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer m);
+
+ /**
+ * Destructor.
+ */
+ virtual ~CRANRepository();
+
+ virtual void invalidate() const;
+ };
+
+ /**
+ * 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.8.0/paludis/repositories/cran/cran_repository.sr b/0.8.0/paludis/repositories/cran/cran_repository.sr
new file mode 100644
index 0000000..fb4344d
--- /dev/null
+++ b/0.8.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 package_database "const PackageDatabase *"
+ 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
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.8.0/paludis/repositories/cran/cran_repository_TEST.cc b/0.8.0/paludis/repositories/cran/cran_repository_TEST.cc
new file mode 100644
index 0000000..850b0c4
--- /dev/null
+++ b/0.8.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;
+ AssociativeCollection<std::string, std::string>::Pointer 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");
+ CRANRepository::Pointer repo(CRANRepository::make_cran_repository(
+ &env, env.package_database().raw_pointer(), 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;
+ AssociativeCollection<std::string, std::string>::Pointer 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");
+ CRANRepository::Pointer repo(CRANRepository::make_cran_repository(
+ &env, env.package_database().raw_pointer(), 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.8.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh b/0.8.0/paludis/repositories/cran/cran_repository_TEST_cleanup.sh
new file mode 100755
index 0000000..d304922
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/cran/cran_repository_TEST_setup.sh b/0.8.0/paludis/repositories/cran/cran_repository_TEST_setup.sh
new file mode 100755
index 0000000..93fdbee
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/fake/Makefile.am b/0.8.0/paludis/repositories/fake/Makefile.am
new file mode 100644
index 0000000..820ba2a
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/Makefile.am
@@ -0,0 +1,31 @@
+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
+paludis_repositories_lib_LTLIBRARIES = libpaludisfakerepository.la
+
+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
+
+libpaludisfakerepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+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
+
+
diff --git a/0.8.0/paludis/repositories/fake/fake_installed_repository.cc b/0.8.0/paludis/repositories/fake/fake_installed_repository.cc
new file mode 100644
index 0000000..9afa130
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/fake_installed_repository.cc
@@ -0,0 +1,49 @@
+/* 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 "fake_installed_repository.hh"
+
+using namespace paludis;
+
+FakeInstalledRepository::FakeInstalledRepository(const RepositoryName & our_name) :
+ FakeRepositoryBase(our_name, RepositoryCapabilities::create()
+ .installable_interface(0)
+ .installed_interface(this)
+ .mask_interface(this)
+ .news_interface(0)
+ .sets_interface(0)
+ .syncable_interface(0)
+ .uninstallable_interface(0)
+ .use_interface(this)
+ .world_interface(0)
+ .mirrors_interface(0)
+ .environment_variable_interface(0)
+ .provides_interface(0)
+ .virtuals_interface(0))
+{
+}
+
+Contents::ConstPointer
+FakeInstalledRepository::do_contents(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ Contents::ConstPointer result(new Contents);
+ return result;
+}
+
diff --git a/0.8.0/paludis/repositories/fake/fake_installed_repository.hh b/0.8.0/paludis/repositories/fake/fake_installed_repository.hh
new file mode 100644
index 0000000..899a916
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/fake_installed_repository.hh
@@ -0,0 +1,41 @@
+/* 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_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
+{
+ class PALUDIS_VISIBLE FakeInstalledRepository :
+ public FakeRepositoryBase,
+ public RepositoryInstalledInterface
+ {
+ protected:
+ virtual Contents::ConstPointer do_contents(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ public:
+ FakeInstalledRepository(const RepositoryName &);
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/fake/fake_repository.cc b/0.8.0/paludis/repositories/fake/fake_repository.cc
new file mode 100644
index 0000000..f573ef0
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/fake_repository.cc
@@ -0,0 +1,47 @@
+/* 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 "fake_repository.hh"
+
+using namespace paludis;
+
+FakeRepository::FakeRepository(const RepositoryName & our_name) :
+ FakeRepositoryBase(our_name, RepositoryCapabilities::create()
+ .installable_interface(this)
+ .installed_interface(0)
+ .mask_interface(this)
+ .news_interface(0)
+ .sets_interface(0)
+ .syncable_interface(0)
+ .uninstallable_interface(0)
+ .use_interface(this)
+ .world_interface(0)
+ .mirrors_interface(0)
+ .environment_variable_interface(0)
+ .provides_interface(0)
+ .virtuals_interface(0))
+{
+}
+
+void
+FakeRepository::do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const
+{
+}
+
diff --git a/0.8.0/paludis/repositories/fake/fake_repository.hh b/0.8.0/paludis/repositories/fake/fake_repository.hh
new file mode 100644
index 0000000..a39c42f
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/fake_repository.hh
@@ -0,0 +1,40 @@
+/* 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_FAKE_FAKE_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_FAKE_FAKE_REPOSITORY_HH 1
+
+#include <paludis/repositories/fake/fake_repository_base.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE FakeRepository :
+ public FakeRepositoryBase,
+ public RepositoryInstallableInterface
+ {
+ protected:
+ virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ public:
+ FakeRepository(const RepositoryName &);
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/fake/fake_repository_base.cc b/0.8.0/paludis/repositories/fake/fake_repository_base.cc
new file mode 100644
index 0000000..efbec73
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/fake_repository_base.cc
@@ -0,0 +1,258 @@
+/* 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 <map>
+#include <paludis/repositories/fake/fake_repository_base.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/collection_concrete.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>,
+ InternalCounted<Implementation<FakeRepositoryBase> >
+ {
+ /// Our category names.
+ CategoryNamePartCollection::Pointer category_names;
+
+ /// Our package names.
+ std::map<CategoryNamePart, PackageNamePartCollection::Pointer > package_names;
+
+ /// Our versions.
+ std::map<QualifiedPackageName, VersionSpecCollection::Pointer > versions;
+
+ /// Our metadata.
+ std::map<std::string, VersionMetadata::Pointer > metadata;
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Constructor.
+ Implementation();
+ };
+
+ Implementation<FakeRepositoryBase>::Implementation() :
+ category_names(new CategoryNamePartCollection::Concrete)
+ {
+ }
+}
+
+FakeRepositoryBase::FakeRepositoryBase(const RepositoryName & our_name, const RepositoryCapabilities & caps) :
+ Repository(our_name, caps),
+ RepositoryMaskInterface(),
+ RepositoryUseInterface(),
+ PrivateImplementationPattern<FakeRepositoryBase>(new Implementation<FakeRepositoryBase>)
+{
+ RepositoryInfoSection::Pointer 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));
+}
+
+CategoryNamePartCollection::ConstPointer
+FakeRepositoryBase::do_category_names() const
+{
+ return _imp->category_names;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+FakeRepositoryBase::do_package_names(const CategoryNamePart & c) const
+{
+ if (! has_category_named(c))
+ throw InternalError(PALUDIS_HERE, "no category named " + stringify(c));
+ QualifiedPackageNameCollection::Pointer result(new QualifiedPackageNameCollection::Concrete);
+ 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;
+}
+
+VersionSpecCollection::ConstPointer
+FakeRepositoryBase::do_version_specs(const QualifiedPackageName & n) const
+{
+ if (! has_category_named(n.category))
+ throw InternalError(PALUDIS_HERE, "no category");
+ if (! has_package_named(n))
+ throw InternalError(PALUDIS_HERE, "no package");
+ return _imp->versions.find(n)->second;
+}
+
+bool
+FakeRepositoryBase::do_has_version(const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ if (! has_category_named(q.category))
+ throw InternalError(PALUDIS_HERE, "no category");
+ if (! has_package_named(q))
+ throw InternalError(PALUDIS_HERE, "no package");
+ 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));
+}
+
+VersionMetadata::Pointer
+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),
+ VersionMetadata::Pointer(new VersionMetadata::Ebuild(PortageDepParser::parse_depend))));
+ VersionMetadata::Pointer r(_imp->metadata.find(stringify(q) + "-" + stringify(v))->second);
+ r->slot = SlotName("0");
+ r->eapi = "0";
+ r->get_ebuild_interface()->keywords = "test";
+ return r;
+}
+
+VersionMetadata::ConstPointer
+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;
+}
+
+UseFlagNameCollection::ConstPointer
+FakeRepositoryBase::do_arch_flags() const
+{
+ return UseFlagNameCollection::ConstPointer(new UseFlagNameCollection::Concrete);
+}
+
+bool
+FakeRepositoryBase::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+FakeRepositoryBase::invalidate() const
+{
+}
+
+UseFlagNameCollection::ConstPointer
+FakeRepositoryBase::do_use_expand_flags() const
+{
+ return UseFlagNameCollection::ConstPointer(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagNameCollection::ConstPointer
+FakeRepositoryBase::do_use_expand_hidden_prefixes() const
+{
+ return UseFlagNameCollection::ConstPointer(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagNameCollection::ConstPointer
+FakeRepositoryBase::do_use_expand_prefixes() const
+{
+ return UseFlagNameCollection::ConstPointer(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;
+}
+
diff --git a/0.8.0/paludis/repositories/fake/fake_repository_base.hh b/0.8.0/paludis/repositories/fake/fake_repository_base.hh
new file mode 100644
index 0000000..287e7d6
--- /dev/null
+++ b/0.8.0/paludis/repositories/fake/fake_repository_base.hh
@@ -0,0 +1,146 @@
+/* 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_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
+{
+ /**
+ * 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,
+ 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 UseFlagNameCollection::ConstPointer do_arch_flags() const;
+ virtual UseFlagNameCollection::ConstPointer do_use_expand_flags() const;
+ virtual UseFlagNameCollection::ConstPointer do_use_expand_hidden_prefixes() const;
+ virtual UseFlagNameCollection::ConstPointer 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;
+
+ /* end of RepositoryUseInterface */
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual CategoryNamePartCollection::ConstPointer do_category_names() const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual VersionMetadata::ConstPointer 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;
+
+ protected:
+ /**
+ * Constructor.
+ */
+ FakeRepositoryBase(const RepositoryName & name, const RepositoryCapabilities & caps);
+
+ 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.
+ */
+ VersionMetadata::Pointer 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).
+ */
+ VersionMetadata::Pointer add_version(
+ const std::string & c, const std::string & p, const std::string & v)
+ {
+ return add_version(CategoryNamePart(c) + PackageNamePart(p), VersionSpec(v));
+ }
+
+ /**
+ * A non-constant smart pointer to ourself.
+ */
+ typedef CountedPtr<FakeRepositoryBase, count_policy::InternalCountTag> Pointer;
+
+ /**
+ * A constant smart pointer to ourself.
+ */
+ typedef CountedPtr<const FakeRepositoryBase, count_policy::InternalCountTag> ConstPointer;
+
+ virtual void invalidate() const;
+ };
+}
+
+
+#endif
diff --git a/0.8.0/paludis/repositories/nothing/Makefile.am b/0.8.0/paludis/repositories/nothing/Makefile.am
new file mode 100644
index 0000000..54b1338
--- /dev/null
+++ b/0.8.0/paludis/repositories/nothing/Makefile.am
@@ -0,0 +1,40 @@
+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
+paludis_repositories_lib_LTLIBRARIES = libpaludisnothingrepository.la
+libpaludisnothingrepository_la_SOURCES = nothing_repository.cc nothing_repository.hh
+libpaludisnothingrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+paludis_repositories_nothing_includedir = $(includedir)/paludis/repositories/nothing/
+
+libpaludisnothingrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+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 > $@
+
diff --git a/0.8.0/paludis/repositories/nothing/nothing_repository.cc b/0.8.0/paludis/repositories/nothing/nothing_repository.cc
new file mode 100644
index 0000000..4c9127e
--- /dev/null
+++ b/0.8.0/paludis/repositories/nothing/nothing_repository.cc
@@ -0,0 +1,256 @@
+/* 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 "config.h"
+
+#include <paludis/repositories/nothing/nothing_repository.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> :
+ InternalCounted<Implementation<NothingRepository> >
+ {
+ /// Our name
+ std::string name;
+
+ /// Our location
+ FSEntry location;
+
+ /// Sync URL
+ std::string sync;
+
+ /// Sync exclude file
+ std::string sync_exclude;
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Constructor.
+ Implementation(const NothingRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+ };
+
+ Implementation<NothingRepository>::Implementation(const NothingRepositoryParams & p) :
+ name(p.name),
+ location(p.location),
+ sync(p.sync),
+ sync_exclude(p.sync_exclude)
+ {
+ }
+
+ Implementation<NothingRepository>::~Implementation()
+ {
+ }
+}
+
+NothingRepository::NothingRepository(const NothingRepositoryParams & p) try :
+ Repository(RepositoryName(p.name),
+ RepositoryCapabilities::create()
+ .mask_interface(0)
+ .installable_interface(0)
+ .installed_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)),
+ PrivateImplementationPattern<NothingRepository>(new Implementation<NothingRepository>(p))
+{
+ RepositoryInfoSection::Pointer config_info(new RepositoryInfoSection("Configuration information"));
+ config_info->add_kv("sync", _imp->sync);
+ config_info->add_kv("sync_exclude", _imp->sync_exclude);
+ 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;
+}
+
+CategoryNamePartCollection::ConstPointer
+NothingRepository::do_category_names() const
+{
+ CategoryNamePartCollection::Pointer result(new CategoryNamePartCollection::Concrete);
+ return result;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+NothingRepository::do_package_names(const CategoryNamePart &) const
+{
+ QualifiedPackageNameCollection::Pointer result(new QualifiedPackageNameCollection::Concrete);
+ return result;
+}
+
+VersionSpecCollection::ConstPointer
+NothingRepository::do_version_specs(const QualifiedPackageName &) const
+{
+ return VersionSpecCollection::Pointer(new VersionSpecCollection::Concrete);
+}
+
+bool
+NothingRepository::do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+VersionMetadata::ConstPointer
+NothingRepository::do_version_metadata(
+ const QualifiedPackageName & q, const VersionSpec & v) const
+{
+ Log::get_instance()->message(ll_warning, lc_context, "has_version failed for request for '" +
+ stringify(q) + "-" + stringify(v) + "' in repository '" +
+ stringify(name()) + "'");
+ return VersionMetadata::ConstPointer(new VersionMetadata::Ebuild(
+ PortageDepParser::parse_depend));
+}
+
+CountedPtr<Repository>
+NothingRepository::make_nothing_repository(
+ const Environment * const,
+ const PackageDatabase * const,
+ AssociativeCollection<std::string, std::string>::ConstPointer 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 + "':");
+
+ 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)).empty())
+ ; // nothing
+
+ 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_exclude;
+ if (m->end() == m->find("sync_exclude") || ((sync_exclude = m->find("sync_exclude")->second)).empty())
+ ; // nothing
+
+ return CountedPtr<Repository>(new NothingRepository(NothingRepositoryParams::create()
+ .name(name)
+ .location(location)
+ .sync(sync)
+ .sync_exclude(sync_exclude)));
+}
+
+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;
+
+ std::string::size_type p(_imp->sync.find("://")), q(_imp->sync.find(":"));
+ if (std::string::npos == p)
+ throw NoSuchSyncerError(_imp->sync);
+
+ SyncOptions opts(_imp->sync_exclude);
+
+ SyncerMaker::get_instance()->find_maker(_imp->sync.substr(0, std::min(p, q)))(
+ stringify(_imp->location), _imp->sync.substr(q < p ? q + 1 : 0))->sync(opts);
+
+ return true;
+}
+
+void
+NothingRepository::invalidate() const
+{
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_nothing_repository PALUDIS_ATTRIBUTE((used)) (
+ "nothing", &NothingRepository::make_nothing_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/nothing/nothing_repository.hh b/0.8.0/paludis/repositories/nothing/nothing_repository.hh
new file mode 100644
index 0000000..16cc679
--- /dev/null
+++ b/0.8.0/paludis/repositories/nothing/nothing_repository.hh
@@ -0,0 +1,116 @@
+/* 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_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 CategoryNamePartCollection::ConstPointer do_category_names() const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual VersionMetadata::ConstPointer do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_is_licence(const std::string &) const;
+
+ virtual bool do_sync() const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ NothingRepository(const NothingRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static CountedPtr<Repository> make_nothing_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer);
+
+ /**
+ * Destructor.
+ */
+ ~NothingRepository();
+
+ virtual void invalidate() const;
+
+ typedef CountedPtr<NothingRepository, count_policy::InternalCountTag> Pointer;
+ typedef CountedPtr<const NothingRepository, count_policy::InternalCountTag> ConstPointer;
+ };
+
+ /**
+ * 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.8.0/paludis/repositories/nothing/nothing_repository.sr b/0.8.0/paludis/repositories/nothing/nothing_repository.sr
new file mode 100644
index 0000000..fab9d3e
--- /dev/null
+++ b/0.8.0/paludis/repositories/nothing/nothing_repository.sr
@@ -0,0 +1,23 @@
+#!/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_exclude std::string
+
+ allow_named_args
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for a NothingRepository.
+ *
+ * \see NothingRepository
+ * \ingroup grpnothingrepository
+ */
+END
+}
+
+
diff --git a/0.8.0/paludis/repositories/portage/Makefile.am b/0.8.0/paludis/repositories/portage/Makefile.am
new file mode 100644
index 0000000..3d6ff91
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/Makefile.am
@@ -0,0 +1,127 @@
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = portage_repository-sr.hh portage_repository-sr.cc glsa-sr.hh glsa-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
+paludis_repositories_lib_LTLIBRARIES = libpaludisportagerepository.la
+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.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 \
+ portage_repository_ebuild_entries.hh \
+ portage_repository_ebin_entries.hh \
+ make_ebuild_repository.hh \
+ make_ebin_repository.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 \
+ portage_repository_ebuild_entries.cc \
+ portage_repository_ebin_entries.cc \
+ portage_repository_params.cc \
+ make_ebuild_repository.cc \
+ make_ebin_repository.cc \
+ $(paludis_repositories_portage_include_HEADERS)
+
+libpaludisportagerepository_la_LIBADD = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(DYNAMIC_LD_LIBS)
+
+portage_repository_TEST_SOURCES = portage_repository_TEST.cc
+
+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
+
+portage_repository_TEST_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 \
+ 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 \
+ 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_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 > $@
+
+if ENABLE_GLSA
+lib_LTLIBRARIES = libpaludisportagerepositoryxmlthings.la
+libpaludisportagerepositoryxmlthings_la_SOURCES = xml_things.cc
+libpaludisportagerepositoryxmlthings_la_CXXFLAGS = @LIBXML2DEPS_CFLAGS@
+libpaludisportagerepositoryxmlthings_la_LIBADD = @LIBXML2DEPS_LIBS@ \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libxml/libpaludislibxml.la
+
+GLSA_TESTS = xml_things_TEST
+xml_things_TEST_SOURCES = xml_things_TEST.cc
+xml_things_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludisportagerepository.la
+endif
+
+TESTS = portage_repository_TEST $(GLSA_TESTS)
+check_PROGRAMS = $(TESTS)
+
diff --git a/0.8.0/paludis/repositories/portage/glsa.cc b/0.8.0/paludis/repositories/portage/glsa.cc
new file mode 100644
index 0000000..8e44e9f
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/glsa.cc
@@ -0,0 +1,233 @@
+/* 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 "glsa.hh"
+#include <paludis/util/iterator.hh>
+#include <paludis/util/stringify.hh>
+#include <list>
+#include <dlfcn.h>
+#include "config.h"
+
+#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
+
+using namespace paludis;
+
+#include "glsa-sr.cc"
+
+namespace paludis
+{
+ template<>
+ struct Implementation<GLSAPackage> :
+ InternalCounted<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> :
+ InternalCounted<Implementation<GLSA> >
+ {
+ std::string id;
+ std::string title;
+ std::list<GLSAPackage::ConstPointer> 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(GLSAPackage::ConstPointer 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;
+}
+
+namespace
+{
+ struct LibXMLHandle
+ {
+ void * handle;
+ GLSA::Pointer (* 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;
+}
+
+GLSA::Pointer
+GLSA::create_from_xml_file(const std::string & filename)
+{
+#if ENABLE_GLSA
+ 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)");
+#else
+ /* avoid noreturn warning */
+ if (0 == libxmlhandle.handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' because Paludis was built "
+ "without GLSA support");
+#endif
+
+ if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
+ libxmlhandle.create_glsa_from_xml_file_handle = STUPID_CAST(GLSA::Pointer (*)(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)");
+
+ return (*libxmlhandle.create_glsa_from_xml_file_handle)(filename);
+}
+
+GLSAError::GLSAError(const std::string & msg, const std::string & filename) throw () :
+ ConfigurationError("GLSA error: " + msg + (filename.empty() ? "" : " in file " + filename))
+{
+}
+
diff --git a/0.8.0/paludis/repositories/portage/glsa.hh b/0.8.0/paludis/repositories/portage/glsa.hh
new file mode 100644
index 0000000..dc25d8f
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/glsa.hh
@@ -0,0 +1,97 @@
+/* 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_GLSA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_GLSA_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/counted_ptr.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>
+
+ class PALUDIS_VISIBLE GLSAError :
+ public ConfigurationError
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ GLSAError(const std::string & message,
+ const std::string & filename = "") throw ();
+
+ ///\}
+ };
+
+ class PALUDIS_VISIBLE GLSAPackage :
+ private PrivateImplementationPattern<GLSAPackage>,
+ public InternalCounted<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;
+ };
+
+ class PALUDIS_VISIBLE GLSA :
+ private PrivateImplementationPattern<GLSA>,
+ public InternalCounted<GLSA>
+ {
+ public:
+ GLSA();
+ ~GLSA();
+
+ static GLSA::Pointer 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(GLSAPackage::ConstPointer);
+
+ 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.8.0/paludis/repositories/portage/glsa.sr b/0.8.0/paludis/repositories/portage/glsa.sr
new file mode 100644
index 0000000..359ffee
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/make_ebin_repository.cc b/0.8.0/paludis/repositories/portage/make_ebin_repository.cc
new file mode 100644
index 0000000..66acaee
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/make_ebin_repository.cc
@@ -0,0 +1,114 @@
+/* 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 "make_ebin_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;
+
+CountedPtr<Repository>
+paludis::make_ebin_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
+ m->find("repo_file")->second);
+
+ Context context("When making ebin 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");
+
+ FSEntryCollection::Pointer 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 (profiles->empty())
+ throw PortageRepositoryConfigurationError("No profiles have been specified");
+
+ FSEntryCollection::Pointer eclassdirs(new FSEntryCollection::Concrete);
+
+ std::string pkgdir;
+ if (m->end() == m->find("pkgdir") || ((pkgdir = m->find("pkgdir")->second)).empty())
+ pkgdir = location + "/packages";
+
+ 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 sync;
+ if (m->end() == m->find("sync") || ((sync = m->find("sync")->second)).empty())
+ ; // nothing
+
+ std::string sync_exclude;
+ if (m->end() == m->find("sync_exclude") || ((sync_exclude = m->find("sync_exclude")->second)).empty())
+ ; // nothing
+
+ 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 CountedPtr<Repository>(new PortageRepository(PortageRepositoryParams::create()
+ .entry_format("ebin")
+ .environment(env)
+ .package_database(db)
+ .location(location)
+ .profiles(profiles)
+ .cache(FSEntry("/var/empty"))
+ .eclassdirs(eclassdirs)
+ .distdir(FSEntry("/var/empty"))
+ .pkgdir(pkgdir)
+ .securitydir(securitydir)
+ .setsdir(setsdir)
+ .newsdir(newsdir)
+ .sync(sync)
+ .sync_exclude(sync_exclude)
+ .root(root)
+ .buildroot(buildroot)));
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_portage_ebin_repository PALUDIS_ATTRIBUTE((used)) (
+ "ebin", &make_ebin_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/portage/make_ebin_repository.hh b/0.8.0/paludis/repositories/portage/make_ebin_repository.hh
new file mode 100644
index 0000000..efcf2ce
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/make_ebin_repository.hh
@@ -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
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_MAKE_EBIN_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_MAKE_EBIN_REPOSITORY_HH 1
+
+#include <paludis/repositories/portage/portage_repository.hh>
+
+namespace paludis
+{
+ CountedPtr<Repository>
+ make_ebin_repository(const Environment * const,
+ const PackageDatabase * const,
+ AssociativeCollection<std::string, std::string>::ConstPointer) PALUDIS_VISIBLE;
+
+}
+
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/make_ebuild_repository.cc b/0.8.0/paludis/repositories/portage/make_ebuild_repository.cc
new file mode 100644
index 0000000..b43ffed
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/make_ebuild_repository.cc
@@ -0,0 +1,159 @@
+/* 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 "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;
+
+CountedPtr<Repository>
+paludis::make_ebuild_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer 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");
+
+ FSEntryCollection::Pointer 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");
+
+ FSEntryCollection::Pointer 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 sync;
+ if (m->end() == m->find("sync") || ((sync = m->find("sync")->second)).empty())
+ ; // nothing
+
+ std::string sync_exclude;
+ if (m->end() == m->find("sync_exclude") || ((sync_exclude = m->find("sync_exclude")->second)).empty())
+ ; // nothing
+
+ 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 CountedPtr<Repository>(new PortageRepository(PortageRepositoryParams::create()
+ .entry_format("ebuild")
+ .environment(env)
+ .package_database(db)
+ .location(location)
+ .profiles(profiles)
+ .cache(cache)
+ .eclassdirs(eclassdirs)
+ .distdir(distdir)
+ .pkgdir(FSEntry("/var/empty"))
+ .securitydir(securitydir)
+ .setsdir(setsdir)
+ .newsdir(newsdir)
+ .sync(sync)
+ .sync_exclude(sync_exclude)
+ .root(root)
+ .buildroot(buildroot)));
+}
+
+CountedPtr<Repository>
+paludis::make_portage_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer m)
+{
+ return make_ebuild_repository(env, db, m);
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_portage_ebuild_repository PALUDIS_ATTRIBUTE((used)) (
+ "ebuild", &make_ebuild_repository);
+
+ const RepositoryMaker::RegisterMaker register_portage_portage_repository PALUDIS_ATTRIBUTE((used)) (
+ "portage", &make_portage_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/portage/make_ebuild_repository.hh b/0.8.0/paludis/repositories/portage/make_ebuild_repository.hh
new file mode 100644
index 0000000..83d834f
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/make_ebuild_repository.hh
@@ -0,0 +1,38 @@
+/* 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_MAKE_EBUILD_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_MAKE_EBUILD_REPOSITORY_HH 1
+
+#include <paludis/repositories/portage/portage_repository.hh>
+
+namespace paludis
+{
+ CountedPtr<Repository>
+ make_ebuild_repository(const Environment * const,
+ const PackageDatabase * const,
+ AssociativeCollection<std::string, std::string>::ConstPointer) PALUDIS_VISIBLE;
+
+ CountedPtr<Repository>
+ make_portage_repository(const Environment * const,
+ const PackageDatabase * const,
+ AssociativeCollection<std::string, std::string>::ConstPointer) PALUDIS_VISIBLE;
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/portage_repository.cc b/0.8.0/paludis/repositories/portage/portage_repository.cc
new file mode 100644
index 0000000..127ce7e
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository.cc
@@ -0,0 +1,1004 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006 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/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/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;
+
+namespace paludis
+{
+ /// Map for versions.
+ typedef MakeHashedMap<QualifiedPackageName, VersionSpecCollection::Pointer>::Type VersionsMap;
+
+ /// Map for repository masks.
+ typedef MakeHashedMap<QualifiedPackageName, std::list<PackageDepAtom::ConstPointer> >::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>,
+ VersionMetadata::Pointer>::Type MetadataMap;
+
+ /// Map for virtuals.
+ typedef MakeHashedMap<QualifiedPackageName, PackageDepAtom::ConstPointer>::Type VirtualsMap;
+
+ /**
+ * Implementation data for a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+ template <>
+ struct Implementation<PortageRepository> :
+ InternalCounted<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 UseFlagNameCollection::Pointer arch_flags;
+
+ /// Do we have mirrors?
+ mutable bool has_mirrors;
+
+ /// Mirrors.
+ mutable MirrorMap mirrors;
+
+ /// Constructor.
+ Implementation(PortageRepository * const, const PortageRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+
+ /// Invalidate our cache.
+ void invalidate() const;
+
+ /// (Empty) provides map.
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ /// Load profiles, if we haven't already.
+ inline void need_profiles() const;
+
+ /// Our profile handler.
+ mutable PortageRepositoryProfile::Pointer profile_ptr;
+
+ /// Our news handler.
+ mutable PortageRepositoryNews::Pointer news_ptr;
+
+ /// Our sets handler.
+ mutable PortageRepositorySets::Pointer sets_ptr;
+
+ /// Our metadata handler.
+ mutable PortageRepositoryEntries::Pointer entries_ptr;
+
+ /// Our virtuals
+ mutable VirtualsMap our_virtuals;
+
+ /// Have we loaded our virtuals?
+ bool has_our_virtuals;
+ };
+
+ Implementation<PortageRepository>::Implementation(PortageRepository * const repo,
+ const PortageRepositoryParams & p) :
+ params(p),
+ has_category_names(false),
+ has_repo_mask(false),
+ has_virtuals(false),
+ arch_flags(0),
+ has_mirrors(false),
+ profile_ptr(0),
+ news_ptr(new PortageRepositoryNews(params.environment, repo, p)),
+ sets_ptr(new PortageRepositorySets(params.environment, repo, p)),
+ entries_ptr(PortageRepositoryEntriesMaker::get_instance()->find_maker(
+ params.entry_format)(params.environment, repo, p)),
+ has_our_virtuals(false)
+ {
+ }
+
+ Implementation<PortageRepository>::~Implementation()
+ {
+ }
+
+ void
+ Implementation<PortageRepository>::need_profiles() const
+ {
+ if (profile_ptr)
+ return;
+
+ profile_ptr.assign(new PortageRepositoryProfile(
+ params.environment, *params.profiles));
+ }
+
+ void
+ Implementation<PortageRepository>::invalidate() const
+ {
+ profile_ptr.zero();
+ has_category_names = false;
+ category_names.clear();
+ package_names.clear();
+ version_specs.clear();
+ metadata.clear();
+ repo_mask.clear();
+ has_repo_mask = false;
+ has_virtuals = false;
+ arch_flags.assign(0);
+ has_mirrors = false;
+ mirrors.clear();
+ }
+}
+
+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)),
+ 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.
+ RepositoryInfoSection::Pointer 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("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", "portage");
+ 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_exclude", _imp->params.sync_exclude);
+
+ _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;
+ }
+ };
+}
+
+CategoryNamePartCollection::ConstPointer
+PortageRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+
+ need_category_names();
+
+ CategoryNamePartCollection::Pointer 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;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+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 QualifiedPackageNameCollection::Pointer(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;
+
+ QualifiedPackageNameCollection::Pointer 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;
+}
+
+VersionSpecCollection::ConstPointer
+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 VersionSpecCollection::Pointer(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);
+ VersionSpecCollection::Pointer 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()) + ":");
+
+ 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()) + ":");
+
+ VersionSpecCollection::Pointer 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.");
+
+ std::string modified_location(FSEntry(location).basename());
+ std::replace(modified_location.begin(), modified_location.end(), '/', '-');
+ return RepositoryName("x-" + modified_location);
+}
+
+VersionMetadata::ConstPointer
+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())));
+
+ VersionMetadata::Pointer 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)
+ {
+ PackageDepAtom::ConstPointer 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<PackageDepAtom::ConstPointer>::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 *) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_state_ignoring_masks(f);
+}
+
+bool
+PortageRepository::do_query_use_mask(const UseFlagName & u, const PackageDatabaseEntry *e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_masked(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);
+}
+
+UseFlagNameCollection::ConstPointer
+PortageRepository::do_arch_flags() const
+{
+ if (! _imp->arch_flags)
+ {
+ Context context("When loading arch list:");
+
+ LineConfigFile archs(_imp->params.location / "profiles" / "arch.list");
+ _imp->arch_flags.assign(new UseFlagNameCollection::Concrete);
+ std::copy(archs.begin(), archs.end(), create_inserter<UseFlagName>(_imp->arch_flags->inserter()));
+ }
+
+ 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);
+}
+
+DepAtom::Pointer
+PortageRepository::do_package_set(const std::string & s) const
+{
+ if (s == "system")
+ {
+ _imp->need_profiles();
+ return _imp->profile_ptr->system_packages();
+ }
+
+ return _imp->sets_ptr->package_set(s);
+}
+
+SetsCollection::ConstPointer
+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::string::size_type p(_imp->params.sync.find("://")), q(_imp->params.sync.find(":"));
+ if (std::string::npos == p)
+ throw NoSuchSyncerError(_imp->params.sync);
+
+ SyncOptions opts(_imp->params.sync_exclude);
+
+ SyncerMaker::get_instance()->find_maker(_imp->params.sync.substr(0, std::min(p, q)))(
+ stringify(_imp->params.location),
+ _imp->params.sync.substr(q < p ? q + 1 : 0))->sync(opts);
+
+ return true;
+}
+
+void
+PortageRepository::invalidate() const
+{
+ _imp->invalidate();
+}
+
+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);
+}
+
+RepositoryInfo::ConstPointer
+PortageRepository::info(bool verbose) const
+{
+ RepositoryInfo::ConstPointer result_non_verbose(Repository::info(verbose));
+ if (! verbose)
+ return result_non_verbose;
+
+ RepositoryInfo::Pointer 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())
+ {
+ RepositoryInfoSection::Pointer 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)
+ {
+ PackageDatabaseEntryCollection::ConstPointer q(
+ _imp->params.environment->package_database()->query(
+ PackageDepAtom::ConstPointer(new PackageDepAtom(*i)), is_installed_only));
+ 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());
+ RepositoryInfoSection::Pointer 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);
+}
+
+PortageRepository::VirtualsCollection::ConstPointer
+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();
+
+ VirtualsCollection::Pointer 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;
+}
+
+VersionMetadata::ConstPointer
+PortageRepository::virtual_package_version_metadata(const RepositoryVirtualsEntry & p,
+ const VersionSpec & v) const
+{
+ VersionMetadata::ConstPointer m(version_metadata(p.provided_by_atom->package(), v));
+ VersionMetadata::Virtual::Pointer result(new VersionMetadata::Virtual(
+ PortageDepParser::parse_depend, PackageDatabaseEntry(
+ p.provided_by_atom->package(), v, name())));
+
+ result->slot = m->slot;
+ result->license_string = m->license_string;
+ result->eapi = m->eapi;
+ result->deps = VersionMetadataDeps(&PortageDepParser::parse_depend,
+ "=" + stringify(p.provided_by_atom->package()) + "-" + stringify(v),
+ "=" + stringify(p.provided_by_atom->package()) + "-" + stringify(v), "");
+
+ return result;
+
+}
+
+UseFlagNameCollection::ConstPointer
+PortageRepository::do_use_expand_flags() const
+{
+ _imp->need_profiles();
+
+ UseFlagNameCollection::Pointer 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;
+}
+
+UseFlagNameCollection::ConstPointer
+PortageRepository::do_use_expand_prefixes() const
+{
+ _imp->need_profiles();
+
+ UseFlagNameCollection::Pointer 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;
+}
+
+UseFlagNameCollection::ConstPointer
+PortageRepository::do_use_expand_hidden_prefixes() const
+{
+ _imp->need_profiles();
+
+ UseFlagNameCollection::Pointer 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) + "'");
+}
+
diff --git a/0.8.0/paludis/repositories/portage/portage_repository.hh b/0.8.0/paludis/repositories/portage/portage_repository.hh
new file mode 100644
index 0000000..fc52d9c
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository.hh
@@ -0,0 +1,166 @@
+/* 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_PORTAGE_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_PORTAGE_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/repositories/portage/portage_repository_params.hh>
+#include <string>
+
+/** \file
+ * Declaration for the PortageRepository class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class PackageDatabase;
+ class PortageRepositoryProfile;
+ class PortageRepositoryNews;
+
+ /**
+ * A PortageRepository is a Repository that handles the layout used by
+ * Portage for the main Gentoo tree.
+ *
+ * \ingroup grpportagerepository
+ */
+ 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 CategoryNamePartCollection::ConstPointer do_category_names() const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual VersionMetadata::ConstPointer 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 DepAtom::Pointer do_package_set(const std::string &) const;
+
+ virtual SetsCollection::ConstPointer sets_list() const;
+
+ virtual bool do_sync() const;
+
+ virtual VirtualsCollection::ConstPointer virtual_packages() const;
+
+ virtual VersionMetadata::ConstPointer 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 UseFlagNameCollection::ConstPointer do_arch_flags() const;
+ virtual UseFlagNameCollection::ConstPointer do_use_expand_flags() const;
+ virtual UseFlagNameCollection::ConstPointer 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 UseFlagNameCollection::ConstPointer do_use_expand_prefixes() const;
+
+ /* end of RepositoryUseInterface */
+
+ public:
+ virtual RepositoryInfo::ConstPointer info(bool verbose) const;
+
+ /**
+ * Constructor.
+ */
+ PortageRepository(const PortageRepositoryParams &);
+
+ /**
+ * Destructor.
+ */
+ ~PortageRepository();
+
+ virtual void invalidate() 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;
+
+ typedef CountedPtr<PortageRepository, count_policy::InternalCountTag> Pointer;
+ typedef CountedPtr<const PortageRepository, count_policy::InternalCountTag> ConstPointer;
+
+ ///\name Information about PortageRepository
+ ///\{
+
+ std::string profile_variable(const std::string &) const;
+
+ typedef libwrapiter::ForwardIterator<PortageRepository, std::pair<
+ const QualifiedPackageName, PackageDepAtom::ConstPointer> > OurVirtualsIterator;
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_TEST.cc b/0.8.0/paludis/repositories/portage/portage_repository_TEST.cc
new file mode 100644
index 0000000..1310d6e
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_TEST.cc
@@ -0,0 +1,666 @@
+/* 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/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.
+ *
+ * \ingroup grptestcases
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test PortageRepository repository names.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryRepoNameTest : TestCase
+ {
+ PortageRepositoryRepoNameTest() : TestCase("repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo1");
+ keys->insert("profile", "portage_repository_TEST_dir/repo1/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "test-repo-1");
+ }
+ } test_portage_repository_repo_name;
+
+ /**
+ * \test Test PortageRepository repository with no names.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryNoRepoNameTest : TestCase
+ {
+ PortageRepositoryNoRepoNameTest() : TestCase("no repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo2");
+ keys->insert("profile", "portage_repository_TEST_dir/repo2/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "x-repo2");
+ }
+ } test_portage_repository_no_repo_name;
+
+ /**
+ * \test Test PortageRepository repository empty names.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryEmptyRepoNameTest : TestCase
+ {
+ PortageRepositoryEmptyRepoNameTest() : TestCase("empty repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo3");
+ keys->insert("profile", "portage_repository_TEST_dir/repo3/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "x-repo3");
+ }
+ } test_portage_repository_empty_repo_name;
+
+ /**
+ * \test Test PortageRepository repository has_category_named.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryHasCategoryNamedTest : TestCase
+ {
+ PortageRepositoryHasCategoryNamedTest() : TestCase("has category named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo1");
+ keys->insert("profile", "portage_repository_TEST_dir/repo1/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryCategoryNamesTest : TestCase
+ {
+ PortageRepositoryCategoryNamesTest() : TestCase("category names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo1");
+ keys->insert("profile", "portage_repository_TEST_dir/repo1/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ CategoryNamePartCollection::ConstPointer 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryHasPackageNamedTest : TestCase
+ {
+ PortageRepositoryHasPackageNamedTest() : TestCase("has package named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryHasPackageNamedCachedTest : TestCase
+ {
+ PortageRepositoryHasPackageNamedCachedTest() : TestCase("has package named cached") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryPackageNamesTest : TestCase
+ {
+ PortageRepositoryPackageNamesTest() : TestCase("package names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ QualifiedPackageNameCollection::ConstPointer names(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryBadPackageNamesTest : TestCase
+ {
+ PortageRepositoryBadPackageNamesTest() : TestCase("bad package names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo5");
+ keys->insert("profile", "portage_repository_TEST_dir/repo5/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ QualifiedPackageNameCollection::ConstPointer names(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryHasVersionTest : TestCase
+ {
+ PortageRepositoryHasVersionTest() : TestCase("has version") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryVersionsTest : TestCase
+ {
+ PortageRepositoryVersionsTest() : TestCase("versions") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo4");
+ keys->insert("profile", "portage_repository_TEST_dir/repo4/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ VersionSpecCollection::ConstPointer versions(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryDuffVersionsTest : TestCase
+ {
+ PortageRepositoryDuffVersionsTest() : TestCase("duff versions") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo8");
+ keys->insert("profile", "portage_repository_TEST_dir/repo8/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ VersionSpecCollection::ConstPointer versions(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryMetadataCachedTest : TestCase
+ {
+ PortageRepositoryMetadataCachedTest() : TestCase("metadata cached") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo6");
+ keys->insert("profile", "portage_repository_TEST_dir/repo6/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ VersionMetadata::ConstPointer m(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryMetadataUncachedTest : TestCase
+ {
+ PortageRepositoryMetadataUncachedTest() : TestCase("metadata uncached") { }
+
+ bool skip() const
+ {
+ return ! getenv_with_default("SANDBOX_ON", "").empty();
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo7");
+ keys->insert("profile", "portage_repository_TEST_dir/repo7/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ VersionMetadata::ConstPointer m(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryMetadataUnparsableTest : TestCase
+ {
+ PortageRepositoryMetadataUnparsableTest() : TestCase("metadata unparsable") { }
+
+ bool skip() const
+ {
+ return ! getenv_with_default("SANDBOX_ON", "").empty();
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo7");
+ keys->insert("profile", "portage_repository_TEST_dir/repo7/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ VersionMetadata::ConstPointer m(0);
+
+ 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.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryQueryUseTest : TestCase
+ {
+ PortageRepositoryQueryUseTest() : TestCase("USE query") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo9");
+ keys->insert("profile", "portage_repository_TEST_dir/repo9/profiles/profile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), 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_disabled);
+ }
+ }
+ } test_portage_repository_query_use;
+
+ /**
+ * \test Test PortageRepository query_profile_masks functions.
+ *
+ * \ingroup grptestcases
+ */
+ struct PortageRepositoryQueryProfileMasksTest : TestCase
+ {
+ PortageRepositoryQueryProfileMasksTest() : TestCase("profiles package.mask") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "portage");
+ keys->insert("location", "portage_repository_TEST_dir/repo10");
+ keys->insert("profiles", "portage_repository_TEST_dir/repo10/profiles/profile/subprofile");
+ PortageRepository::Pointer repo(make_ebuild_repository(
+ &env, env.package_database().raw_pointer(), 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.8.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh b/0.8.0/paludis/repositories/portage/portage_repository_TEST_cleanup.sh
new file mode 100755
index 0000000..8c0b290
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_TEST_setup.sh b/0.8.0/paludis/repositories/portage/portage_repository_TEST_setup.sh
new file mode 100755
index 0000000..5fc9373
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_ebin_entries.cc b/0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.cc
new file mode 100644
index 0000000..de948c6
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.cc
@@ -0,0 +1,379 @@
+/* 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 <paludis/repositories/portage/portage_repository_ebin_entries.hh>
+#include <paludis/repositories/portage/portage_repository.hh>
+
+#include <paludis/config_file.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/ebin.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 PortageRepositoryEbinEntries.
+ *
+ * \ingroup grpportagerepository
+ */
+ template<>
+ struct Implementation<PortageRepositoryEbinEntries> :
+ InternalCounted<Implementation<PortageRepositoryEbinEntries> >
+ {
+ const Environment * const environment;
+ PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ Implementation(const Environment * const e, PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k)
+ {
+ }
+ };
+}
+
+PortageRepositoryEbinEntries::PortageRepositoryEbinEntries(
+ const Environment * const e, PortageRepository * const p, const PortageRepositoryParams & k) :
+ PortageRepositoryEntries(".ebin"),
+ PrivateImplementationPattern<PortageRepositoryEbinEntries>(new
+ Implementation<PortageRepositoryEbinEntries>(e, p, k))
+{
+}
+
+PortageRepositoryEbinEntries::~PortageRepositoryEbinEntries()
+{
+}
+
+VersionMetadata::Pointer
+PortageRepositoryEbinEntries::generate_version_metadata(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ VersionMetadata::Pointer result(new VersionMetadata::Ebin(PortageDepParser::parse_depend));
+
+ FSEntry ebin_file(_imp->params.location);
+ ebin_file /= stringify(q.category);
+ ebin_file /= stringify(q.package);
+ ebin_file /= (stringify(q.package) + "-" + stringify(v) + ".ebin");
+
+ if (ebin_file.is_regular_file())
+ {
+ KeyValueConfigFile f(ebin_file);
+ result->deps.build_depend_string = f.get("depend");
+ result->deps.run_depend_string = f.get("rdepend");
+ result->deps.post_depend_string = f.get("pdepend");
+ result->slot = SlotName(f.get("slot"));
+ result->license_string = f.get("license");
+ result->eapi = f.get("eapi");
+ result->homepage = f.get("homepage");
+ result->description = f.get("description");
+ result->get_ebuild_interface()->provide_string = f.get("provide");
+ result->get_ebuild_interface()->restrict_string = f.get("restrict");
+ result->get_ebuild_interface()->keywords = f.get("keywords");
+ result->get_ebuild_interface()->iuse = f.get("iuse");
+ result->get_ebuild_interface()->inherited = f.get("inherited");
+ result->get_ebin_interface()->bin_uri = f.get("bin_uri");
+ result->get_ebin_interface()->src_repository = RepositoryName(f.get("src_repository"));
+ }
+ else
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, _imp->portage_repository->name())));
+
+ return result;
+
+}
+
+void
+PortageRepositoryEbinEntries::install(const QualifiedPackageName & q, const VersionSpec & v,
+ const InstallOptions & o, PortageRepositoryProfile::ConstPointer p) const
+{
+ VersionMetadata::ConstPointer metadata(_imp->portage_repository->version_metadata(q, v));
+
+ if (! _imp->portage_repository->has_version(q, v))
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since has_version failed");
+
+ PackageDatabaseEntry e(q, v, _imp->portage_repository->name());
+
+ std::string binaries, flat_bin_uri;
+ {
+ std::set<std::string> already_in_binaries;
+
+ /* make B */
+ DepAtom::ConstPointer f_atom(PortageDepParser::parse(metadata->get_ebin_interface()->bin_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_binaries.end() == already_in_binaries.find((*ff)->text()))
+ {
+ binaries.append((*ff)->text());
+ already_in_binaries.insert((*ff)->text());
+ }
+ }
+ else
+ {
+ if (already_in_binaries.end() == already_in_binaries.find((*ff)->text().substr(pos + 1)))
+ {
+ binaries.append((*ff)->text().substr(pos + 1));
+ already_in_binaries.insert((*ff)->text().substr(pos + 1));
+ }
+ }
+ binaries.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_bin_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 s_pos(mirror.find('/'));
+
+ if (std::string::npos == s_pos)
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since SRC_URI is broken");
+
+ if (! _imp->portage_repository->is_mirror(mirror.substr(0, s_pos)))
+ throw PackageInstallActionError("Can't install '" + stringify(s_pos) + "-"
+ + stringify(v) + "' since SRC_URI references unknown mirror:// '" +
+ mirror.substr(0, s_pos) + "'");
+
+ for (Environment::MirrorIterator
+ m(_imp->params.environment->begin_mirrors(mirror.substr(0, s_pos))),
+ m_end(_imp->params.environment->end_mirrors(mirror.substr(0, s_pos))) ;
+ m != m_end ; ++m)
+ flat_bin_uri.append(m->second + "/" + mirror.substr(s_pos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(mirror.substr(0, s_pos))),
+ m_end(_imp->portage_repository->end_mirrors(mirror.substr(0, s_pos))) ;
+ m != m_end ; ++m)
+ flat_bin_uri.append(m->second + "/" + mirror.substr(s_pos + 1) + " ");
+ }
+ else
+ flat_bin_uri.append((*ff)->text());
+ flat_bin_uri.append(" ");
+
+ /* add mirror://gentoo/ entries */
+ std::string master_mirror(strip_trailing_string(stringify(_imp->portage_repository->name()), "x-"));
+ if (_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_bin_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_bin_uri.append(m->second + "/" + (*ff)->text().substr(pos + 1) + " ");
+ }
+ }
+ }
+
+ std::string use;
+ {
+ std::set<UseFlagName> iuse;
+ WhitespaceTokeniser::get_instance()->tokenise(metadata->get_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 */
+ AssociativeCollection<std::string, std::string>::Pointer 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);
+
+ /* 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 */
+ UseFlagNameCollection::ConstPointer possible_values_from_env(_imp->params.environment->
+ known_use_expand_names(*x, &e));
+ std::copy(possible_values_from_env->begin(), possible_values_from_env->end(),
+ std::inserter(possible_values, possible_values.end()));
+
+ 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 + " ";
+ expand_vars->erase(i);
+ }
+ value.append(stringify(*u));
+ expand_vars->insert(stringify(*x), value);
+ }
+ }
+
+ binaries = strip_trailing(binaries, " ");
+
+ EbinFetchCommand fetch_cmd(EbinCommandParams::create()
+ .environment(_imp->params.environment)
+ .db_entry(&e)
+ .src_repository(metadata->get_ebin_interface()->src_repository)
+ .ebin_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package))
+ .pkgdir(_imp->params.pkgdir)
+ .buildroot(_imp->params.buildroot),
+
+ EbinFetchCommandParams::create()
+ .b(binaries)
+ .flat_bin_uri(flat_bin_uri)
+ .root(stringify(_imp->params.root) + "/")
+ .profiles(_imp->params.profiles));
+
+ fetch_cmd();
+
+ if (o.fetch_only)
+ return;
+
+ EbinInstallCommand install_cmd(EbinCommandParams::create()
+ .environment(_imp->params.environment)
+ .db_entry(&e)
+ .src_repository(metadata->get_ebin_interface()->src_repository)
+ .ebin_dir(_imp->params.location / stringify(q.category) /
+ stringify(q.package))
+ .pkgdir(_imp->params.pkgdir)
+ .buildroot(_imp->params.buildroot),
+
+ EbinInstallCommandParams::create()
+ .b(binaries)
+ .use(use)
+ .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)
+ .slot(SlotName(metadata->slot)));
+
+ install_cmd();
+}
+
+std::string
+PortageRepositoryEbinEntries::get_environment_variable(const QualifiedPackageName & q,
+ const VersionSpec & v, const std::string & s,
+ PortageRepositoryProfile::ConstPointer) const
+{
+ VersionMetadata::ConstPointer metadata(_imp->portage_repository->version_metadata(q, v));
+
+ if (s == "DEPEND")
+ return metadata->deps.build_depend_string;
+ if (s == "RDEPEND")
+ return metadata->deps.run_depend_string;
+ if (s == "PDEPEND")
+ return metadata->deps.post_depend_string;
+
+ if (s == "SLOT")
+ return stringify(metadata->slot);
+ if (s == "LICENSE")
+ return metadata->license_string;
+ if (s == "EAPI")
+ return metadata->eapi;
+ if (s == "HOMEPAGE")
+ return metadata->homepage;
+ if (s == "DESCRIPTION")
+ return metadata->description;
+
+ if (s == "PROVIDE")
+ return metadata->get_ebuild_interface()->provide_string;
+ if (s == "SRC_URI")
+ return metadata->get_ebuild_interface()->src_uri;
+ if (s == "RESTRICT")
+ return metadata->get_ebuild_interface()->restrict_string;
+ if (s == "KEYWORDS")
+ return metadata->get_ebuild_interface()->keywords;
+ if (s == "IUSE")
+ return metadata->get_ebuild_interface()->iuse;
+ if (s == "VIRTUAL")
+ return metadata->get_ebuild_interface()->inherited;
+
+ if (s == "BIN_URI")
+ return metadata->get_ebin_interface()->bin_uri;
+ if (s == "SRC_REPOSITORY")
+ return stringify(metadata->get_ebin_interface()->src_repository);
+
+ PackageDatabaseEntry for_package(q, v, _imp->portage_repository->name());
+ throw EnvironmentVariableActionError("Couldn't get environment variable '" +
+ stringify(s) + "' for package '" + stringify(for_package) + "'");
+}
+
+PortageRepositoryEbinEntries::Pointer
+PortageRepositoryEbinEntries::make_portage_repository_ebin_entries(
+ const Environment * const e, PortageRepository * const r, const PortageRepositoryParams & p)
+{
+ return Pointer(new PortageRepositoryEbinEntries(e, r, p));
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const PortageRepositoryEntriesMaker::RegisterMaker register_portage_repository_ebin_entries PALUDIS_ATTRIBUTE((used)) (
+ "ebin", &PortageRepositoryEbinEntries::make_portage_repository_ebin_entries);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.hh b/0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.hh
new file mode 100644
index 0000000..bc7eda7
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_ebin_entries.hh
@@ -0,0 +1,71 @@
+/* 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_EBIN_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_EBIN_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 PortageRepositoryEbinEntries class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class FSEntry;
+ class PortageRepository;
+
+ /**
+ * PortageRepositoryEntries handler for ebins.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE PortageRepositoryEbinEntries :
+ public PortageRepositoryEntries,
+ private PrivateImplementationPattern<PortageRepositoryEbinEntries>
+ {
+ public:
+ static PortageRepositoryEbinEntries::Pointer
+ make_portage_repository_ebin_entries(const Environment * const,
+ PortageRepository * const, const PortageRepositoryParams &);
+
+ PortageRepositoryEbinEntries(const Environment * const,
+ PortageRepository * const portage_repository,
+ const PortageRepositoryParams &);
+
+ virtual ~PortageRepositoryEbinEntries();
+
+ virtual VersionMetadata::Pointer generate_version_metadata(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::string get_environment_variable(const QualifiedPackageName &,
+ const VersionSpec &, const std::string & var,
+ PortageRepositoryProfile::ConstPointer) const;
+
+ virtual void install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &, PortageRepositoryProfile::ConstPointer) const;
+ };
+}
+
+#endif
+
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.cc b/0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.cc
new file mode 100644
index 0000000..562e93c
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.cc
@@ -0,0 +1,556 @@
+/* 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 <paludis/repositories/portage/portage_repository_ebuild_entries.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 PortageRepositoryEbuildEntries.
+ *
+ * \ingroup grpportagerepository
+ */
+ template<>
+ struct Implementation<PortageRepositoryEbuildEntries> :
+ InternalCounted<Implementation<PortageRepositoryEbuildEntries> >
+ {
+ const Environment * const environment;
+ PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ Implementation(const Environment * const e, PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k)
+ {
+ }
+ };
+}
+
+PortageRepositoryEbuildEntries::PortageRepositoryEbuildEntries(
+ const Environment * const e, PortageRepository * const p, const PortageRepositoryParams & k) :
+ PortageRepositoryEntries(".ebuild"),
+ PrivateImplementationPattern<PortageRepositoryEbuildEntries>(new
+ Implementation<PortageRepositoryEbuildEntries>(e, p, k))
+{
+}
+
+PortageRepositoryEbuildEntries::~PortageRepositoryEbuildEntries()
+{
+}
+
+VersionMetadata::Pointer
+PortageRepositoryEbuildEntries::generate_version_metadata(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ VersionMetadata::Pointer result(new VersionMetadata::Ebuild(PortageDepParser::parse_depend));
+
+ FSEntry cache_file(_imp->params.cache);
+ cache_file /= stringify(q.category);
+ cache_file /= stringify(q.package) + "-" + stringify(v);
+
+ bool ok(false);
+ if (cache_file.is_regular_file())
+ {
+ std::ifstream cache(stringify(cache_file).c_str());
+ std::string line;
+
+ if (cache)
+ {
+ std::getline(cache, line); result->deps.build_depend_string = line;
+ std::getline(cache, line); result->deps.run_depend_string = line;
+ std::getline(cache, line); result->slot = SlotName(line);
+ std::getline(cache, line); result->get_ebuild_interface()->src_uri = line;
+ std::getline(cache, line); result->get_ebuild_interface()->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->get_ebuild_interface()->keywords = line;
+ std::getline(cache, line); result->get_ebuild_interface()->inherited = line;
+ std::getline(cache, line); result->get_ebuild_interface()->iuse = line;
+ std::getline(cache, line);
+ std::getline(cache, line); result->deps.post_depend_string = line;
+ std::getline(cache, line); result->get_ebuild_interface()->provide_string = line;
+ std::getline(cache, line); result->eapi = line;
+
+ // check mtimes
+ time_t cache_time(cache_file.mtime());
+ ok = true;
+
+ if ((_imp->params.location / stringify(q.category) /
+ stringify(q.package) /
+ (stringify(q.package) + "-" + stringify(v)
+ + ".ebuild")).mtime() > cache_time)
+ ok = false;
+ else
+ {
+ FSEntry timestamp(_imp->params.location / "metadata" / "timestamp");
+ if (timestamp.exists())
+ cache_time = timestamp.mtime();
+
+ std::list<std::string> inherits;
+ WhitespaceTokeniser::get_instance()->tokenise(
+ stringify(result->get_ebuild_interface()->inherited),
+ std::back_inserter(inherits));
+ for (FSEntryCollection::Iterator e(_imp->params.eclassdirs->begin()),
+ e_end(_imp->params.eclassdirs->end()) ; e != e_end ; ++e)
+ for (std::list<std::string>::const_iterator i(inherits.begin()),
+ i_end(inherits.end()) ; i != i_end ; ++i)
+ {
+ if ((*e / (*i + ".eclass")).exists())
+ if (((*e / (*i + ".eclass"))).mtime() > cache_time)
+ ok = false;
+ }
+ }
+
+ if (! ok)
+ Log::get_instance()->message(ll_warning, lc_no_context, "Stale cache file at '"
+ + stringify(cache_file) + "'");
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Couldn't read the cache file at '"
+ + stringify(cache_file) + "'");
+ }
+
+ 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???");
+ }
+
+ 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 DepAtom::ConstPointer 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
+PortageRepositoryEbuildEntries::install(const QualifiedPackageName & q, const VersionSpec & v,
+ const InstallOptions & o, PortageRepositoryProfile::ConstPointer p) const
+{
+ if (! _imp->portage_repository->has_version(q, v))
+ {
+ throw PackageInstallActionError("Can't install '" + stringify(q) + "-"
+ + stringify(v) + "' since has_version failed");
+ }
+
+ VersionMetadata::ConstPointer 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->get_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 */
+ DepAtom::ConstPointer f_atom(PortageDepParser::parse(metadata->get_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 */
+ DepAtom::ConstPointer g_atom(PortageDepParser::parse(
+ metadata->get_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->get_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 */
+ AssociativeCollection<std::string, std::string>::Pointer 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 */
+ UseFlagNameCollection::ConstPointer 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));
+
+ 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)
+ .slot(SlotName(metadata->slot)));
+
+ install_cmd();
+}
+
+std::string
+PortageRepositoryEbuildEntries::get_environment_variable(const QualifiedPackageName & q,
+ const VersionSpec & v, const std::string & var,
+ PortageRepositoryProfile::ConstPointer) 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();
+}
+
+PortageRepositoryEbuildEntries::Pointer
+PortageRepositoryEbuildEntries::make_portage_repository_ebuild_entries(
+ const Environment * const e, PortageRepository * const r, const PortageRepositoryParams & p)
+{
+ return Pointer(new PortageRepositoryEbuildEntries(e, r, p));
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const PortageRepositoryEntriesMaker::RegisterMaker register_portage_repository_ebuild_entries PALUDIS_ATTRIBUTE((used)) (
+ "ebuild", &PortageRepositoryEbuildEntries::make_portage_repository_ebuild_entries);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.hh b/0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.hh
new file mode 100644
index 0000000..a3fb2f8
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_ebuild_entries.hh
@@ -0,0 +1,70 @@
+/* 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_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 PortageRepositoryEbuildEntries class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class FSEntry;
+ class PortageRepository;
+
+ /**
+ * PortageRepositoryEntries handler for ebuilds.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE PortageRepositoryEbuildEntries :
+ public PortageRepositoryEntries,
+ private PrivateImplementationPattern<PortageRepositoryEbuildEntries>
+ {
+ public:
+ static PortageRepositoryEbuildEntries::Pointer
+ make_portage_repository_ebuild_entries(const Environment * const,
+ PortageRepository * const, const PortageRepositoryParams &);
+
+ PortageRepositoryEbuildEntries(const Environment * const,
+ PortageRepository * const portage_repository,
+ const PortageRepositoryParams &);
+
+ virtual ~PortageRepositoryEbuildEntries();
+
+ virtual VersionMetadata::Pointer generate_version_metadata(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual std::string get_environment_variable(const QualifiedPackageName &,
+ const VersionSpec &, const std::string & var,
+ PortageRepositoryProfile::ConstPointer) const;
+
+ virtual void install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &, PortageRepositoryProfile::ConstPointer) const;
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_entries.cc b/0.8.0/paludis/repositories/portage/portage_repository_entries.cc
new file mode 100644
index 0000000..c891b04
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_entries.cc
@@ -0,0 +1,38 @@
+/* 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"
+
+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 + "'")
+{
+}
+
+
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_entries.hh b/0.8.0/paludis/repositories/portage/portage_repository_entries.hh
new file mode 100644
index 0000000..0ba2f7a
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_entries.hh
@@ -0,0 +1,126 @@
+/* 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_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/counted_ptr.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
+ */
+ class PALUDIS_VISIBLE PortageRepositoryEntries :
+ public InternalCounted<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 VersionMetadata::Pointer 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,
+ PortageRepositoryProfile::ConstPointer) const = 0;
+
+ virtual void install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &, PortageRepositoryProfile::ConstPointer) const = 0;
+ };
+
+ /**
+ * Thrown if a repository of the specified type does not exist.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grprepository
+ */
+ class PALUDIS_VISIBLE NoSuchPortageRepositoryEntriesType : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ NoSuchPortageRepositoryEntriesType(const std::string & format) throw ();
+ };
+
+ /**
+ * Virtual constructor for PortageRepositoryEntries.
+ *
+ * \ingroup grprepository
+ */
+ typedef VirtualConstructor<std::string,
+ PortageRepositoryEntries::Pointer (*) (const Environment * const, PortageRepository * const,
+ const PortageRepositoryParams &),
+ virtual_constructor_not_found::ThrowException<NoSuchPortageRepositoryEntriesType> >
+ PortageRepositoryEntriesMaker;
+
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_entry.cc b/0.8.0/paludis/repositories/portage/portage_repository_entry.cc
new file mode 100644
index 0000000..ea568cd
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_exceptions.cc b/0.8.0/paludis/repositories/portage/portage_repository_exceptions.cc
new file mode 100644
index 0000000..f8e1186
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_exceptions.hh b/0.8.0/paludis/repositories/portage/portage_repository_exceptions.hh
new file mode 100644
index 0000000..945182e
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_news.cc b/0.8.0/paludis/repositories/portage/portage_repository_news.cc
new file mode 100644
index 0000000..8936219
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_news.cc
@@ -0,0 +1,284 @@
+/* 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/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> :
+ InternalCounted<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::Pointer(
+ new PackageDepAtom(*i)), is_installed_only)->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);
+ FSEntryCollection::ConstPointer 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> :
+ InternalCounted<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.8.0/paludis/repositories/portage/portage_repository_news.hh b/0.8.0/paludis/repositories/portage/portage_repository_news.hh
new file mode 100644
index 0000000..2a7dacb
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_news.hh
@@ -0,0 +1,134 @@
+/* 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_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
+ */
+ class PALUDIS_VISIBLE PortageRepositoryNews :
+ private PrivateImplementationPattern<PortageRepositoryNews>,
+ private InstantiationPolicy<PortageRepositoryNews, instantiation_method::NonCopyableTag>,
+ public InternalCounted<PortageRepositoryNews>
+ {
+ 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
+ */
+ 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.8.0/paludis/repositories/portage/portage_repository_params.cc b/0.8.0/paludis/repositories/portage/portage_repository_params.cc
new file mode 100644
index 0000000..d520725
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_params.hh b/0.8.0/paludis/repositories/portage/portage_repository_params.hh
new file mode 100644
index 0000000..5381766
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/portage_repository_params.sr b/0.8.0/paludis/repositories/portage/portage_repository_params.sr
new file mode 100644
index 0000000..61d2044
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_params.sr
@@ -0,0 +1,34 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_PortageRepositoryParams()
+{
+ key entry_format std::string
+ key environment "const Environment *"
+ key package_database "const PackageDatabase *"
+ key location FSEntry
+ key profiles FSEntryCollection::ConstPointer
+ key cache FSEntry
+ key distdir FSEntry
+ key pkgdir FSEntry
+ key eclassdirs FSEntryCollection::ConstPointer
+ key setsdir FSEntry
+ key securitydir FSEntry
+ key newsdir FSEntry
+ key sync std::string
+ key sync_exclude std::string
+ key root FSEntry
+ key buildroot FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a PortageRepository
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_profile.cc b/0.8.0/paludis/repositories/portage/portage_repository_profile.cc
new file mode 100644
index 0000000..987973f
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_profile.cc
@@ -0,0 +1,686 @@
+/* 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 <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 paludis
+{
+ /**
+ * Implementation for PortageRepositoryProfile.
+ *
+ * \ingroup grpportagerepository
+ * \see PortageRepositoryProfile
+ */
+ template<>
+ class Implementation<PortageRepositoryProfile> :
+ public InternalCounted<PortageRepositoryProfile>
+ {
+ public:
+ ///\name Convenience typedefs
+ ///\{
+
+ typedef MakeHashedMap<UseFlagName, UseFlagState>::Type UseMap;
+ typedef MakeHashedSet<UseFlagName>::Type UseFlagSet;
+ typedef MakeHashedMap<std::string, std::string>::Type EnvironmentVariablesMap;
+ typedef MakeHashedMap<QualifiedPackageName,
+ std::list<std::pair<PackageDepAtom::ConstPointer, UseFlagName> > >::Type PackageUseMaskMap;
+ typedef MakeHashedMap<QualifiedPackageName, PackageDepAtom::ConstPointer>::Type VirtualsMap;
+ typedef MakeHashedMap<QualifiedPackageName, std::list<PackageDepAtom::ConstPointer> >::Type PackageMaskMap;
+
+ ///\}
+
+ 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 add_use_expand_to_use();
+ void make_vars_from_file_vars();
+ void handle_profile_arch_var();
+
+ ProfileFile use_mask_file;
+ ProfileFile package_use_mask_file;
+ ProfileFile use_force_file;
+ ProfileFile package_use_force_file;
+ ProfileFile packages_file;
+ ProfileFile virtuals_file;
+ ProfileFile package_mask_file;
+
+ public:
+ ///\name General variables
+ ///\{
+
+ const Environment * const env;
+
+ ///\}
+
+ ///\name Use flags
+ ///\{
+
+ UseMap use;
+ UseFlagSet use_expand;
+ UseFlagSet use_expand_hidden;
+ UseFlagSet use_mask;
+ UseFlagSet use_force;
+ PackageUseMaskMap package_use_mask;
+ PackageUseMaskMap package_use_force;
+
+ ///\}
+
+ ///\name Environment variables
+ ///\{
+
+ EnvironmentVariablesMap environment_variables;
+
+ ///\}
+
+ ///\name System package set
+ ///\{
+
+ AllDepAtom::Pointer system_packages;
+ GeneralSetDepTag::Pointer system_tag;
+
+ ///\}
+
+ ///\name Virtuals
+ ///\{
+
+ VirtualsMap virtuals;
+
+ ///\}
+
+ ///\name Masks
+ ///\{
+
+ PackageMaskMap package_mask;
+
+ ///\}
+
+ ///\name Queries
+ ///\{
+
+ bool use_mask_or_force(const UseFlagName & u, const PackageDatabaseEntry * const e,
+ const std::string & mask_or_force, const UseFlagSet & global,
+ const PackageUseMaskMap & package) const;
+
+ ///\}
+
+ ///\name Basic operations
+ ///\{
+
+ Implementation(const Environment * const e, const FSEntryCollection & dirs) :
+ env(e),
+ system_packages(new AllDepAtom),
+ system_tag(new GeneralSetDepTag("system"))
+ {
+ for (FSEntryCollection::Iterator d(dirs.begin()), d_end(dirs.end()) ;
+ d != d_end ; ++d)
+ load_profile_directory_recursively(*d);
+
+ add_use_expand_to_use();
+ make_vars_from_file_vars();
+ 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;
+ }
+
+ load_profile_parent(dir);
+ load_profile_make_defaults(dir);
+
+ use_mask_file.add_file(dir / "use.mask");
+ package_use_mask_file.add_file(dir / "package.use.mask");
+ use_force_file.add_file(dir / "use.force");
+ package_use_force_file.add_file(dir / "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");
+
+ try
+ {
+ std::list<std::string> uses;
+ WhitespaceTokeniser::get_instance()->tokenise(file.get("USE"), std::back_inserter(uses));
+
+ for (std::list<std::string>::const_iterator u(uses.begin()), u_end(uses.end()) ;
+ u != u_end ; ++u)
+ if ('-' == u->at(0))
+ use[UseFlagName(u->substr(1))] = use_disabled;
+ else
+ use[UseFlagName(*u)] = use_enabled;
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ WhitespaceTokeniser::get_instance()->tokenise(
+ file.get("USE_EXPAND"), create_inserter<UseFlagName>(
+ std::inserter(use_expand, use_expand.begin())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE_EXPAND failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ WhitespaceTokeniser::get_instance()->tokenise(
+ file.get("USE_EXPAND_HIDDEN"), create_inserter<UseFlagName>(
+ std::inserter(use_expand_hidden, use_expand_hidden.begin())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading USE_EXPAND_HIDDEN failed due to exception: "
+ + e.message() + " (" + e.what() + ")");
+ }
+
+ for (KeyValueConfigFile::Iterator k(file.begin()), k_end(file.end()) ;
+ k != k_end ; ++k)
+ {
+ Log::get_instance()->message(ll_debug, lc_context, "Profile environment variable '" +
+ stringify(k->first) + "' is '" + stringify(k->second) + "'");
+ environment_variables[k->first] = k->second;
+ }
+}
+
+void
+Implementation<PortageRepositoryProfile>::make_vars_from_file_vars()
+{
+ try
+ {
+ Context context("When parsing use.mask:");
+ std::copy(use_mask_file.begin(), use_mask_file.end(), create_inserter<UseFlagName>(
+ std::inserter(use_mask, use_mask.begin())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading use.mask "
+ " failed due to exception: " + stringify(e.message()) + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ Context context("When parsing use.force:");
+ std::copy(use_force_file.begin(), use_force_file.end(), create_inserter<UseFlagName>(
+ std::inserter(use_force, use_force.begin())));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading use.force "
+ " failed due to exception: " + stringify(e.message()) + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ Context context("When parsing package.use.mask:");
+
+ for (ProfileFile::Iterator line(package_use_mask_file.begin()), line_end(package_use_mask_file.end()) ;
+ line != line_end ; ++line)
+ {
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(tokens));
+ if (tokens.size() < 2)
+ continue;
+
+ std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end());
+ PackageDepAtom::ConstPointer d(new PackageDepAtom(*t++));
+ QualifiedPackageName p(d->package());
+
+ PackageUseMaskMap::iterator i(package_use_mask.find(p));
+ if (package_use_mask.end() == i)
+ i = package_use_mask.insert(std::make_pair(p, std::list<std::pair<PackageDepAtom::ConstPointer,
+ UseFlagName> >())).first;
+
+ for ( ; t != t_end ; ++t)
+ {
+ if (0 == t->compare(0, 1, "-"))
+ {
+ UseFlagName r(t->substr(1));
+ bool found(false);
+ for (std::list<std::pair<PackageDepAtom::ConstPointer, UseFlagName> >::iterator
+ e(i->second.begin()), e_end(i->second.end()) ; e != e_end ; )
+ {
+ if (stringify(*e->first) == stringify(*d) && e->second == r)
+ {
+ found = true;
+ i->second.erase(e++);
+ }
+ else
+ ++e;
+ }
+
+ if (! found)
+ Log::get_instance()->message(ll_qa, lc_context, "No match for '" + stringify(*line) + "'");
+ }
+ else
+ i->second.push_back(std::make_pair(d, UseFlagName(*t)));
+ }
+ }
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading package.use.mask "
+ " failed due to exception: " + stringify(e.message()) + " (" + e.what() + ")");
+ }
+
+ try
+ {
+ Context context("When parsing package.use.force:");
+
+ for (ProfileFile::Iterator line(package_use_force_file.begin()), line_end(package_use_force_file.end()) ;
+ line != line_end ; ++line)
+ {
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(tokens));
+ if (tokens.size() < 2)
+ continue;
+
+ std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end());
+ PackageDepAtom::ConstPointer d(new PackageDepAtom(*t++));
+ QualifiedPackageName p(d->package());
+
+ PackageUseMaskMap::iterator i(package_use_force.find(p));
+ if (package_use_force.end() == i)
+ i = package_use_force.insert(std::make_pair(p, std::list<std::pair<PackageDepAtom::ConstPointer,
+ UseFlagName> >())).first;
+
+ for ( ; t != t_end ; ++t)
+ {
+ if (0 == t->compare(0, 1, "-"))
+ {
+ UseFlagName r(t->substr(1));
+ bool found(false);
+ for (std::list<std::pair<PackageDepAtom::ConstPointer, UseFlagName> >::iterator
+ e(i->second.begin()), e_end(i->second.end()) ; e != e_end ; )
+ {
+ if (stringify(*e->first) == stringify(*d) && e->second == r)
+ {
+ found = true;
+ i->second.erase(e++);
+ }
+ else
+ ++e;
+ }
+
+ if (! found)
+ Log::get_instance()->message(ll_qa, lc_context, "No match for '" + stringify(*line) + "'");
+ }
+ else
+ i->second.push_back(std::make_pair(d, UseFlagName(*t)));
+ }
+ }
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading package.use.mask "
+ " failed due to exception: " + e.message() + " (" + e.what() + ")");
+ }
+
+ 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 + "':");
+ PackageDepAtom::Pointer 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, PackageDepAtom::Pointer(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
+ {
+ PackageDepAtom::ConstPointer 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() + ")");
+ }
+ }
+}
+
+bool
+Implementation<PortageRepositoryProfile>::use_mask_or_force(
+ const UseFlagName & u, const PackageDatabaseEntry * const e, const std::string & mask_or_force,
+ const UseFlagSet & global, const PackageUseMaskMap & package) const
+{
+ Context context("When querying profile use " + mask_or_force + " status of '" + stringify(u) +
+ (e ? "' for '" + stringify(*e) + "'" : "'"));
+
+ if (global.end() != global.find(u))
+ return true;
+
+ if (0 == e)
+ return false;
+
+ PackageUseMaskMap::const_iterator i(package.find(e->name));
+ if (package.end() == i)
+ return false;
+
+ for (std::list<std::pair<PackageDepAtom::ConstPointer, UseFlagName> >::const_iterator
+ j(i->second.begin()), j_end(i->second.end()) ; j != j_end ; ++j)
+ {
+ static int depth(0);
+ if (depth > 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context,
+ "depth > 3 on entry '" + stringify(*j->first) + "'");
+
+ if (j->first->use_requirements_ptr())
+ continue;
+ if (u == j->second && match_package(env, j->first, e))
+ return true;
+ }
+ else
+ {
+ Save<int> save_depth(&depth, depth + 1);
+ if (u == j->second && match_package(env, j->first, e))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+Implementation<PortageRepositoryProfile>::add_use_expand_to_use()
+{
+ Context context("When adding USE_EXPAND to USE:");
+
+ 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[UseFlagName(lower_x + "_" + *u)] = use_enabled;
+ }
+}
+
+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");
+
+ try
+ {
+ UseFlagName arch(arch_s);
+
+ use[arch] = use_enabled;
+ use_force.insert(arch);
+ if (use_mask.end() != use_mask.find(arch))
+ throw PortageRepositoryConfigurationError("ARCH USE '" + arch_s + "' is use masked");
+ }
+ catch (const NameError & e)
+ {
+ throw PortageRepositoryConfigurationError("ARCH variable has invalid value '" + arch_s + "'");
+ }
+}
+
+PortageRepositoryProfile::PortageRepositoryProfile(
+ const Environment * const env, const FSEntryCollection & location) :
+ PrivateImplementationPattern<PortageRepositoryProfile>(
+ new Implementation<PortageRepositoryProfile>(env, location))
+{
+}
+
+PortageRepositoryProfile::~PortageRepositoryProfile()
+{
+}
+
+bool
+PortageRepositoryProfile::use_masked(const UseFlagName & u,
+ const PackageDatabaseEntry * const e) const
+{
+ return _imp->use_mask_or_force(u, e, "mask", _imp->use_mask, _imp->package_use_mask);
+}
+
+bool
+PortageRepositoryProfile::use_forced(const UseFlagName & u,
+ const PackageDatabaseEntry * const e) const
+{
+ return _imp->use_mask_or_force(u, e, "force", _imp->use_force, _imp->package_use_force);
+}
+
+UseFlagState
+PortageRepositoryProfile::use_state_ignoring_masks(const UseFlagName & u) const
+{
+ Implementation<PortageRepositoryProfile>::UseMap::const_iterator p(_imp->use.find(u));
+ if (_imp->use.end() == p)
+ return use_unspecified;
+ return p->second;
+}
+
+std::string
+PortageRepositoryProfile::environment_variable(const std::string & s) const
+{
+ Implementation<PortageRepositoryProfile>::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;
+ }
+}
+
+AllDepAtom::Pointer
+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
+{
+ Implementation<PortageRepositoryProfile>::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<PackageDepAtom::ConstPointer>::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.8.0/paludis/repositories/portage/portage_repository_profile.hh b/0.8.0/paludis/repositories/portage/portage_repository_profile.hh
new file mode 100644
index 0000000..c1520dd
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_profile.hh
@@ -0,0 +1,125 @@
+/* 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_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
+ */
+ class PALUDIS_VISIBLE PortageRepositoryProfile :
+ private PrivateImplementationPattern<PortageRepositoryProfile>,
+ private InstantiationPolicy<PortageRepositoryProfile, instantiation_method::NonCopyableTag>,
+ public InternalCounted<PortageRepositoryProfile>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ PortageRepositoryProfile(const Environment * const env, 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;
+
+ ///\}
+
+ ///\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
+ ///\{
+
+ AllDepAtom::Pointer system_packages() const;
+
+ ///\}
+
+ ///\name Virtuals
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<PortageRepositoryProfile,
+ const std::pair<const QualifiedPackageName, PackageDepAtom::ConstPointer> > VirtualsIterator;
+
+ VirtualsIterator begin_virtuals() const;
+ VirtualsIterator end_virtuals() const;
+ VirtualsIterator find_virtual() const;
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/portage_repository_profile_file.cc b/0.8.0/paludis/repositories/portage/portage_repository_profile_file.cc
new file mode 100644
index 0000000..1301e0e
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_profile_file.cc
@@ -0,0 +1,81 @@
+/* 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_profile_file.hh"
+#include <paludis/util/log.hh>
+#include <paludis/config_file.hh>
+#include <list>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ProfileFile> :
+ InternalCounted<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
+ _imp->lines.erase(i);
+ }
+ 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.8.0/paludis/repositories/portage/portage_repository_profile_file.hh b/0.8.0/paludis/repositories/portage/portage_repository_profile_file.hh
new file mode 100644
index 0000000..2cda5ed
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_profile_file.hh
@@ -0,0 +1,45 @@
+/* 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
+{
+ 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.8.0/paludis/repositories/portage/portage_repository_sets.cc b/0.8.0/paludis/repositories/portage/portage_repository_sets.cc
new file mode 100644
index 0000000..9126263
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/portage_repository_sets.cc
@@ -0,0 +1,379 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006 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.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> :
+ InternalCounted<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()
+{
+}
+
+
+DepAtom::Pointer
+PortageRepositorySets::package_set(const std::string & s) const
+{
+ if ("system" == s)
+ throw InternalError(PALUDIS_HERE, "system set should've been handled by PortageRepository");
+ else if ("security" == s)
+ return security_set(false);
+ else if ("insecurity" == s)
+ return security_set(true);
+ else if ((_imp->params.setsdir / (s + ".conf")).exists())
+ {
+ GeneralSetDepTag::Pointer tag(new GeneralSetDepTag(s));
+
+ FSEntry ff(_imp->params.setsdir / (s + ".conf"));
+ Context context("When loading package set '" + s + "' from '" + stringify(ff) + "':");
+
+ AllDepAtom::Pointer 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 '*'");
+ PackageDepAtom::Pointer atom(new PackageDepAtom(tokens.at(0)));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+ else if ("*" == tokens.at(0))
+ {
+ PackageDepAtom::Pointer atom(new PackageDepAtom(tokens.at(1)));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+ else if ("?" == tokens.at(0))
+ {
+ PackageDepAtom::Pointer p(new PackageDepAtom(tokens.at(1)));
+ p->set_tag(tag);
+ if (! _imp->environment->package_database()->query(
+ PackageDepAtom::Pointer(new PackageDepAtom(p->package())),
+ is_installed_only)->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 DepAtom::Pointer(0);
+}
+
+SetsCollection::ConstPointer
+PortageRepositorySets::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ SetsCollection::Pointer result(new SetsCollection::Concrete);
+ result->insert("security");
+ result->insert("system");
+
+ /*
+ * TODO: get rid of unnecessary copying and just put this in a for loop
+ * (need to read some doxygen pages on FSEntry first)
+ */
+ 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)
+ result->insert(stringify(*f));
+ }
+ catch (const paludis::DirOpenError & e)
+ {
+ }
+
+ return result;
+}
+
+namespace
+{
+ inline
+ PackageDepAtom::Pointer make_atom(const PackageDatabaseEntry & e)
+ {
+ QualifiedPackageName n(e.name);
+ VersionSpec v(e.version);
+
+ std::string s("=" + stringify(n) + "-" + stringify(v));
+ return PackageDepAtom::Pointer(new PackageDepAtom(s));
+ }
+}
+
+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;
+ }
+}
+
+DepAtom::Pointer
+PortageRepositorySets::security_set(bool insecurity) const
+{
+ Context context("When building security or insecurity package set:");
+ AllDepAtom::Pointer security_packages(new AllDepAtom);
+
+ if (!_imp->params.securitydir.is_directory())
+ return security_packages;
+
+ std::map<std::string, GLSADepTag::Pointer> 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
+ {
+ GLSA::ConstPointer 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)
+ {
+ PackageDatabaseEntryCollection::ConstPointer candidates(_imp->environment->package_database()->query(
+ PackageDepAtom::Pointer(new PackageDepAtom(stringify(glsa_pkg->name()))),
+ insecurity ? is_either : is_installed_only));
+ 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(), GLSADepTag::Pointer(
+ new GLSADepTag(glsa->id(), glsa->title()))));
+
+ if (insecurity)
+ {
+ PackageDepAtom::Pointer 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);
+
+ PackageDatabaseEntryCollection::ConstPointer available(
+ _imp->environment->package_database()->query(PackageDepAtom::Pointer(
+ new PackageDepAtom(stringify(glsa_pkg->name()))), is_uninstalled_only));
+ 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;
+
+ PackageDepAtom::Pointer 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.8.0/paludis/repositories/portage/portage_repository_sets.hh b/0.8.0/paludis/repositories/portage/portage_repository_sets.hh
new file mode 100644
index 0000000..85b361b
--- /dev/null
+++ b/0.8.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 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
+ */
+ class PALUDIS_VISIBLE PortageRepositorySets :
+ private PrivateImplementationPattern<PortageRepositorySets>,
+ private InstantiationPolicy<PortageRepositorySets, instantiation_method::NonCopyableTag>,
+ public InternalCounted<PortageRepositorySets>
+ {
+ 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.
+ */
+ DepAtom::Pointer package_set(const std::string & s) const;
+
+ /**
+ * Fetch the security or insecurity set.
+ */
+ DepAtom::Pointer security_set(bool insecure) const;
+
+ /**
+ * Give a list of all the sets in this repo.
+ */
+ SetsCollection::ConstPointer sets_list() const;
+ };
+}
+
+
+#endif
diff --git a/0.8.0/paludis/repositories/portage/xml_things.cc b/0.8.0/paludis/repositories/portage/xml_things.cc
new file mode 100644
index 0000000..bfca771
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/xml_things.cc
@@ -0,0 +1,188 @@
+/* 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 <libxml/tree.h>
+#include <libxml/parser.h>
+#include <paludis/repositories/portage/glsa.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/config_file.hh>
+#include <paludis/libxml/libxml.hh>
+#include <set>
+
+using namespace paludis;
+
+extern "C"
+{
+ GLSA::Pointer create_glsa_from_xml_file(const std::string &);
+}
+
+namespace
+{
+ class Handler
+ {
+ private:
+ GLSA::Pointer _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, GLSAPackage::Pointer 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, GLSAPackage::Pointer 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 name;
+ handle_package_name(doc, n->properties, name);
+ GLSAPackage::Pointer pkg(new GLSAPackage(QualifiedPackageName(name)));
+ 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);
+ }
+
+ }
+
+ GLSA::Pointer glsa()
+ {
+ return _glsa;
+ }
+ };
+}
+
+GLSA::Pointer
+create_glsa_from_xml_file(const std::string & filename)
+{
+ LibXmlPtrHolder<xmlDocPtr> 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, xmlDocGetRootElement(xml_doc));
+ return h.glsa();
+}
+
diff --git a/0.8.0/paludis/repositories/portage/xml_things_TEST.cc b/0.8.0/paludis/repositories/portage/xml_things_TEST.cc
new file mode 100644
index 0000000..748fc08
--- /dev/null
+++ b/0.8.0/paludis/repositories/portage/xml_things_TEST.cc
@@ -0,0 +1,92 @@
+/* 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/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()
+ {
+ GLSA::Pointer 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()
+ {
+ GLSA::Pointer 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.8.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh b/0.8.0/paludis/repositories/portage/xml_things_TEST_cleanup.sh
new file mode 100755
index 0000000..5e0843f
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/portage/xml_things_TEST_setup.sh b/0.8.0/paludis/repositories/portage/xml_things_TEST_setup.sh
new file mode 100755
index 0000000..530af80
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/vdb/Makefile.am b/0.8.0/paludis/repositories/vdb/Makefile.am
new file mode 100644
index 0000000..5be12db
--- /dev/null
+++ b/0.8.0/paludis/repositories/vdb/Makefile.am
@@ -0,0 +1,66 @@
+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
+paludis_repositories_lib_LTLIBRARIES = libpaludisvdbrepository.la
+libpaludisvdbrepository_la_SOURCES = vdb_repository.cc vdb_repository.hh
+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_repository-sr.hh \
+ vdb_repository-sr.cc
+
+libpaludisvdbrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+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
+
+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 > $@
+
+
diff --git a/0.8.0/paludis/repositories/vdb/vdb_repository.cc b/0.8.0/paludis/repositories/vdb/vdb_repository.cc
new file mode 100644
index 0000000..2b3e163
--- /dev/null
+++ b/0.8.0/paludis/repositories/vdb/vdb_repository.cc
@@ -0,0 +1,1179 @@
+/* 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/vdb/vdb_repository.hh>
+
+#include <paludis/dep_atom.hh>
+#include <paludis/dep_atom_flattener.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/ebuild.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/config_file.hh>
+#include <paludis/match_package.hh>
+#include <paludis/package_database.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>
+
+/** \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.
+ VersionMetadata::Pointer metadata;
+
+ /// Our built USE flags.
+ std::set<UseFlagName> use;
+
+ /// Constructor
+ VDBEntry(const QualifiedPackageName & n, const VersionSpec & v) :
+ name(n),
+ version(v),
+ metadata(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"));
+ }
+}
+
+namespace
+{
+ /**
+ * 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> :
+ InternalCounted<Implementation<VDBRepository> >
+ {
+ /// Our owning db.
+ const PackageDatabase * const db;
+
+ /// 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;
+
+ /// Do we have entries loaded?
+ mutable bool entries_valid;
+
+ /// Our entries, keep this sorted!
+ mutable std::vector<VDBEntry> entries;
+
+ /// Load entries.
+ void load_entries() const;
+
+ /// Load metadata for one entry.
+ void load_entry(std::vector<VDBEntry>::iterator) const;
+
+ /// Constructor.
+ Implementation(const VDBRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+
+ /// Invalidate.
+ void invalidate() const;
+ };
+
+ Implementation<VDBRepository>::Implementation(const VDBRepositoryParams & p) :
+ db(p.package_database),
+ env(p.environment),
+ location(p.location),
+ root(p.root),
+ buildroot(p.buildroot),
+ world_file(p.world),
+ entries_valid(false)
+ {
+ }
+
+ Implementation<VDBRepository>::~Implementation()
+ {
+ }
+
+ void
+ Implementation<VDBRepository>::load_entries() const
+ {
+ Context context("When loading VDBRepository entries from '" +
+ stringify(location) + "':");
+
+ entries.clear();
+ entries_valid = true;
+ try
+ {
+ for (DirIterator cat_i(location), cat_iend ; cat_i != cat_iend ; ++cat_i)
+ {
+ if (! cat_i->is_directory())
+ continue;
+
+ for (DirIterator pkg_i(*cat_i), pkg_iend ; pkg_i != pkg_iend ; ++pkg_i)
+ {
+ PackageDepAtom atom("=" + cat_i->basename() + "/" + pkg_i->basename());
+ entries.push_back(VDBEntry(atom.package(), *atom.version_spec_ptr()));
+ }
+ }
+
+ std::sort(entries.begin(), entries.end());
+ }
+ catch (...)
+ {
+ entries_valid = false;
+ throw;
+ }
+ }
+
+ void
+ Implementation<VDBRepository>::invalidate() const
+ {
+ entries_valid = false;
+ entries.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 = VersionMetadata::Pointer(new VersionMetadata::Ebuild(PortageDepParser::parse_depend));
+ p->metadata->deps.build_depend_string = file_contents(location, p->name, p->version, "DEPEND");
+ p->metadata->deps.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->get_ebuild_interface()->keywords = "*";
+ p->metadata->get_ebuild_interface()->inherited =
+ file_contents(location, p->name, p->version, "INHERITED");
+ p->metadata->get_ebuild_interface()->iuse =
+ file_contents(location, p->name, p->version, "IUSE");
+ p->metadata->deps.post_depend_string =
+ file_contents(location, p->name, p->version, "PDEPEND");
+ p->metadata->get_ebuild_interface()->provide_string =
+ file_contents(location, p->name, p->version, "PROVIDE");
+ 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 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)),
+ PrivateImplementationPattern<VDBRepository>(new Implementation<VDBRepository>(p))
+{
+ RepositoryInfoSection::Pointer 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("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();
+
+ 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;
+}
+
+CategoryNamePartCollection::ConstPointer
+VDBRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ CategoryNamePartCollection::Pointer 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;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+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()) + ":");
+
+ QualifiedPackageNameCollection::Pointer 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;
+}
+
+VersionSpecCollection::ConstPointer
+VDBRepository::do_version_specs(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ VersionSpecCollection::Pointer 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()) + ":");
+
+ VersionSpecCollection::ConstPointer versions(do_version_specs(q));
+ return versions->end() != versions->find(v);
+}
+
+VersionMetadata::ConstPointer
+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();
+
+ 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;
+ }
+}
+
+Contents::ConstPointer
+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 Contents::ConstPointer(new Contents);
+ }
+
+ Contents::Pointer 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(ContentsEntry::Pointer(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(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(ContentsEntry::Pointer(new ContentsSymEntry(
+ tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return result;
+}
+
+UseFlagState
+VDBRepository::do_query_use(const UseFlagName & f,
+ const PackageDatabaseEntry * const e) const
+{
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ if (e->repository == name())
+ {
+
+ 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);
+}
+
+CountedPtr<Repository>
+VDBRepository::make_vdb_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer m)
+{
+ Context context("When making VDB 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 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 buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = "/var/tmp/paludis";
+
+ return CountedPtr<Repository>(new VDBRepository(VDBRepositoryParams::create()
+ .environment(env)
+ .package_database(db)
+ .location(location)
+ .root(root)
+ .world(world)
+ .buildroot(buildroot)));
+}
+
+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");
+
+ VersionMetadata::ConstPointer metadata(0);
+ 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());
+
+ FSEntryCollection::Pointer 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)));
+
+ CountedPtr<FSEntry, count_policy::ExternalCountTag> load_env(0);
+ if (is_full_env(pkg_dir))
+ load_env.assign(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.raw_pointer()));
+
+ uninstall_cmd();
+}
+
+DepAtom::Pointer
+VDBRepository::do_package_set(const std::string & s) const
+{
+ Context context("When fetching package set '" + s + "' from '" +
+ stringify(name()) + "':");
+
+ if ("everything" == s)
+ {
+ AllDepAtom::Pointer result(new AllDepAtom);
+ GeneralSetDepTag::Pointer tag(new GeneralSetDepTag("everything"));
+
+ 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)
+ {
+ PackageDepAtom::Pointer atom(new PackageDepAtom(p->name));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+
+ return result;
+ }
+ else if ("world" == s)
+ {
+ AllDepAtom::Pointer result(new AllDepAtom);
+ GeneralSetDepTag::Pointer tag(new GeneralSetDepTag("world"));
+
+ if (_imp->world_file.exists())
+ {
+ LineConfigFile world(_imp->world_file);
+
+ for (LineConfigFile::Iterator line(world.begin()), line_end(world.end()) ;
+ line != line_end ; ++line)
+ {
+ PackageDepAtom::Pointer atom(new PackageDepAtom(QualifiedPackageName(*line)));
+ atom->set_tag(tag);
+ result->add_child(atom);
+ }
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "World file '" + stringify(_imp->world_file) +
+ "' doesn't exist");
+
+ return result;
+ }
+ else
+ return DepAtom::Pointer(0);
+}
+
+SetsCollection::ConstPointer
+VDBRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ SetsCollection::Pointer result(new SetsCollection::Concrete);
+ result->insert("everything");
+ result->insert("world");
+ return result;
+}
+
+void
+VDBRepository::invalidate() const
+{
+ _imp->invalidate();
+}
+
+void
+VDBRepository::add_to_world(const QualifiedPackageName & n) const
+{
+ Context context("When adding '" + stringify(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 (QualifiedPackageName(*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_from_world(const QualifiedPackageName & 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"));
+}
+
+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) + "'");
+}
+
+RepositoryProvidesInterface::ProvidesCollection::ConstPointer
+VDBRepository::provided_packages() const
+{
+ Context context("When loading VDB PROVIDEs map:");
+
+ Log::get_instance()->message(ll_debug, lc_no_context, "Starting VDB PROVIDEs map creation");
+
+ ProvidesCollection::Pointer 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->get_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;
+
+ DepAtom::ConstPointer 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");
+
+ return result;
+}
+
+VersionMetadata::ConstPointer
+VDBRepository::provided_package_version_metadata(const RepositoryProvidesEntry & p) const
+{
+ VersionMetadata::ConstPointer m(version_metadata(p.provided_by_name, p.version));
+ VersionMetadata::Virtual::Pointer result(new VersionMetadata::Virtual(
+ PortageDepParser::parse_depend, PackageDatabaseEntry(p.provided_by_name,
+ p.version, name())));
+
+ result->slot = m->slot;
+ result->license_string = m->license_string;
+ result->eapi = m->eapi;
+ result->deps = VersionMetadataDeps(&PortageDepParser::parse_depend,
+ stringify(p.provided_by_name), stringify(p.provided_by_name), "");
+
+ return result;
+}
+
+UseFlagNameCollection::ConstPointer
+VDBRepository::do_arch_flags() const
+{
+ return UseFlagNameCollection::ConstPointer(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagNameCollection::ConstPointer
+VDBRepository::do_use_expand_flags() const
+{
+ return UseFlagNameCollection::ConstPointer(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagNameCollection::ConstPointer
+VDBRepository::do_use_expand_prefixes() const
+{
+ return UseFlagNameCollection::ConstPointer(new UseFlagNameCollection::Concrete);
+}
+
+UseFlagNameCollection::ConstPointer
+VDBRepository::do_use_expand_hidden_prefixes() const
+{
+ return UseFlagNameCollection::ConstPointer(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;
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_vdb_repository PALUDIS_ATTRIBUTE((used)) (
+ "vdb", &VDBRepository::make_vdb_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/vdb/vdb_repository.hh b/0.8.0/paludis/repositories/vdb/vdb_repository.hh
new file mode 100644
index 0000000..a1574ed
--- /dev/null
+++ b/0.8.0/paludis/repositories/vdb/vdb_repository.hh
@@ -0,0 +1,174 @@
+/* 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_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 PrivateImplementationPattern<VDBRepository>
+ {
+ protected:
+ virtual bool do_has_category_named(const CategoryNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const;
+
+ virtual CategoryNamePartCollection::ConstPointer do_category_names() const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &, const VersionSpec &) const;
+
+ virtual VersionMetadata::ConstPointer do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual Contents::ConstPointer do_contents(
+ 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 DepAtom::Pointer do_package_set(const std::string &) 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 UseFlagNameCollection::ConstPointer do_arch_flags() const;
+ virtual UseFlagNameCollection::ConstPointer do_use_expand_flags() const;
+ virtual UseFlagNameCollection::ConstPointer 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 UseFlagNameCollection::ConstPointer do_use_expand_prefixes() const;
+
+ /* end of RepositoryUseInterface */
+
+ public:
+ /**
+ * Constructor.
+ */
+ VDBRepository(const VDBRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static CountedPtr<Repository> make_vdb_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer m);
+
+ /**
+ * Destructor.
+ */
+ ~VDBRepository();
+
+ virtual void invalidate() const;
+
+ virtual void add_to_world(const QualifiedPackageName &) const;
+
+ virtual void remove_from_world(const QualifiedPackageName &) const;
+
+ virtual std::string get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const;
+
+ virtual ProvidesCollection::ConstPointer provided_packages() const;
+
+ virtual VersionMetadata::ConstPointer provided_package_version_metadata(
+ const RepositoryProvidesEntry &) const;
+
+ virtual SetsCollection::ConstPointer sets_list() const;
+
+ typedef CountedPtr<VDBRepository, count_policy::InternalCountTag> Pointer;
+ typedef CountedPtr<const VDBRepository, count_policy::InternalCountTag> ConstPointer;
+ };
+
+ /**
+ * 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.8.0/paludis/repositories/vdb/vdb_repository.sr b/0.8.0/paludis/repositories/vdb/vdb_repository.sr
new file mode 100644
index 0000000..15a21ad
--- /dev/null
+++ b/0.8.0/paludis/repositories/vdb/vdb_repository.sr
@@ -0,0 +1,24 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_VDBRepositoryParams()
+{
+ key environment "const Environment *"
+ key package_database "const PackageDatabase *"
+ key location FSEntry
+ key root FSEntry
+ key world FSEntry
+ key buildroot FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a VDBRepository
+ *
+ * \see VDBRepository
+ * \ingroup grpvdbrepository
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.8.0/paludis/repositories/vdb/vdb_repository_TEST.cc b/0.8.0/paludis/repositories/vdb/vdb_repository_TEST.cc
new file mode 100644
index 0000000..15a8f46
--- /dev/null
+++ b/0.8.0/paludis/repositories/vdb/vdb_repository_TEST.cc
@@ -0,0 +1,238 @@
+/* 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/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.
+ *
+ * \ingroup grptestcases
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test VDBRepository repo names
+ *
+ * \ingroup grptestcases
+ */
+ struct VDBRepositoryRepoNameTest : TestCase
+ {
+ VDBRepositoryRepoNameTest() : TestCase("repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "installed");
+ }
+ } test_vdb_repository_repo_name;
+
+ /**
+ * \test Test VDBRepository has_category_named
+ *
+ * \ingroup grptestcases
+ */
+ struct VDBRepositoryHasCategoryNamedTest : TestCase
+ {
+ VDBRepositoryHasCategoryNamedTest() : TestCase("has category named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), 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
+ *
+ * \ingroup grptestcases
+ */
+ struct VDBRepositoryQueryUseTest : TestCase
+ {
+ VDBRepositoryQueryUseTest() : TestCase("query USE") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), 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->query_use(UseFlagName("flag1"), &e1) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag2"), &e1) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag3"), &e1) == use_disabled);
+
+ TEST_CHECK(repo->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;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-new-file");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ repo->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;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-empty");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ repo->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;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-no-match");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ repo->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;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-match");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ repo->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;
+ AssociativeCollection<std::string, std::string>::Pointer keys(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("format", "vdb");
+ keys->insert("location", "vdb_repository_TEST_dir/repo1");
+ keys->insert("world", "vdb_repository_TEST_dir/world-no-match-no-eol");
+ VDBRepository::Pointer repo(VDBRepository::make_vdb_repository(
+ &env, env.package_database().raw_pointer(), keys));
+ repo->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.8.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh b/0.8.0/paludis/repositories/vdb/vdb_repository_TEST_cleanup.sh
new file mode 100755
index 0000000..e9f03a6
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh b/0.8.0/paludis/repositories/vdb/vdb_repository_TEST_setup.sh
new file mode 100755
index 0000000..138a6b1
--- /dev/null
+++ b/0.8.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.8.0/paludis/repositories/virtuals/Makefile.am b/0.8.0/paludis/repositories/virtuals/Makefile.am
new file mode 100644
index 0000000..d29e451
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/Makefile.am
@@ -0,0 +1,61 @@
+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
+paludis_repositories_lib_LTLIBRARIES = libpaludisvirtualsrepository.la
+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 \
+ $(paludis_repositories_portage_include_HEADERS)
+
+libpaludisvirtualsrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+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 > $@
+
+
+
diff --git a/0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.cc b/0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.cc
new file mode 100644
index 0000000..0d8fafe
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.cc
@@ -0,0 +1,322 @@
+/* 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/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> :
+ InternalCounted<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)),
+ PrivateImplementationPattern<InstalledVirtualsRepository>(
+ new Implementation<InstalledVirtualsRepository>(env))
+{
+ RepositoryInfoSection::Pointer 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;
+
+ RepositoryProvidesInterface::ProvidesCollection::ConstPointer 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;
+}
+
+CountedPtr<Repository>
+InstalledVirtualsRepository::make_installed_virtuals_repository(
+ const Environment * const env,
+ const PackageDatabase * const,
+ AssociativeCollection<std::string, std::string>::ConstPointer)
+{
+ return CountedPtr<Repository>(new InstalledVirtualsRepository(env));
+}
+
+Contents::ConstPointer
+InstalledVirtualsRepository::do_contents(
+ const QualifiedPackageName &, const VersionSpec &) const
+{
+ /* virtual packages don't have any genuine contents. don't return the
+ * content of our real package -- that'll cause extreme confusion with
+ * paludis --owner. */
+
+ return Contents::ConstPointer(new Contents);
+}
+
+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;
+}
+
+VersionMetadata::ConstPointer
+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;
+}
+
+VersionSpecCollection::ConstPointer
+InstalledVirtualsRepository::do_version_specs(const QualifiedPackageName & q) const
+{
+ if (q.category.data() != "virtual")
+ return VersionSpecCollection::Pointer(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()));
+
+ VersionSpecCollection::Pointer result(new VersionSpecCollection::Concrete);
+ for ( ; p.first != p.second ; ++p.first)
+ result->insert(p.first->version);
+
+ return result;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+InstalledVirtualsRepository::do_package_names(const CategoryNamePart & c) const
+{
+ if (c.data() != "virtual")
+ return QualifiedPackageNameCollection::Pointer(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()));
+
+
+ QualifiedPackageNameCollection::Pointer 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;
+}
+
+CategoryNamePartCollection::ConstPointer
+InstalledVirtualsRepository::do_category_names() const
+{
+ need_entries();
+
+ CategoryNamePartCollection::Pointer result(new CategoryNamePartCollection::Concrete);
+#if 0
+ /// \todo: in theory, this can be a lot lot lot faster
+ for (std::vector<VREntry>::const_iterator p(_imp->entries.begin()), p_end(_imp->entries.end()) ;
+ p != p_end ; ++p)
+ result->insert(p->virtual_name.category);
+#else
+ 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() const
+{
+ _imp->has_entries = false;
+ _imp->entries.clear();
+}
+
+void
+InstalledVirtualsRepository::do_uninstall(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const
+{
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_installed_virtuals_repository PALUDIS_ATTRIBUTE((used)) (
+ "installed_virtuals", &InstalledVirtualsRepository::make_installed_virtuals_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.hh b/0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.hh
new file mode 100644
index 0000000..c145ecc
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/installed_virtuals_repository.hh
@@ -0,0 +1,91 @@
+/* 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_VIRTUALS_INSTALLED_VIRTUALS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_VIRTUALS_INSTALLED_VIRTUALS_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE InstalledVirtualsRepository :
+ public Repository,
+ public RepositoryInstalledInterface,
+ public RepositoryUninstallableInterface,
+ public RepositoryMaskInterface,
+ private PrivateImplementationPattern<InstalledVirtualsRepository>
+ {
+ private:
+ void need_entries() const;
+
+ protected:
+ virtual Contents::ConstPointer do_contents(
+ 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 VersionMetadata::ConstPointer do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual CategoryNamePartCollection::ConstPointer 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 &,
+ const InstallOptions &) const;
+
+ public:
+ InstalledVirtualsRepository(const Environment * const env);
+
+ virtual ~InstalledVirtualsRepository();
+
+ static CountedPtr<Repository> make_installed_virtuals_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer);
+
+ virtual void invalidate() const;
+
+ virtual bool can_be_favourite_repository() const
+ {
+ return false;
+ }
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/virtuals/virtuals_repository.cc b/0.8.0/paludis/repositories/virtuals/virtuals_repository.cc
new file mode 100644
index 0000000..631d958
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/virtuals_repository.cc
@@ -0,0 +1,338 @@
+/* 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 "virtuals_repository.hh"
+#include <paludis/package_database.hh>
+#include <paludis/environment.hh>
+#include <paludis/match_package.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/fast_unique_copy.hh>
+#include <paludis/util/log.hh>
+#include "vr_entry.hh"
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<VirtualsRepository> :
+ InternalCounted<Implementation<VirtualsRepository> >
+ {
+ const Environment * const env;
+
+ mutable std::vector<VREntry> entries;
+ mutable bool has_entries;
+
+ Implementation(const Environment * const e) :
+ env(e),
+ has_entries(false)
+ {
+ }
+ };
+}
+
+VirtualsRepository::VirtualsRepository(const Environment * const env) :
+ Repository(RepositoryName("virtuals"), RepositoryCapabilities::create()
+ .installable_interface(this)
+ .mask_interface(this)
+ .installed_interface(0)
+ .use_interface(0)
+ .news_interface(0)
+ .sets_interface(0)
+ .syncable_interface(0)
+ .uninstallable_interface(0)
+ .mirrors_interface(0)
+ .environment_variable_interface(0)
+ .world_interface(0)
+ .provides_interface(0)
+ .virtuals_interface(0)),
+ PrivateImplementationPattern<VirtualsRepository>(
+ new Implementation<VirtualsRepository>(env))
+{
+ RepositoryInfoSection::Pointer config_info(new RepositoryInfoSection("Configuration information"));
+ config_info->add_kv("format", "virtuals");
+ _info->add_section(config_info);
+}
+
+VirtualsRepository::~VirtualsRepository()
+{
+}
+
+void
+VirtualsRepository::need_entries() const
+{
+ if (_imp->has_entries)
+ return;
+
+ Context context("When loading entries for virtuals repository:");
+
+ /* Determine our virtual name -> package mappings. */
+ std::map<QualifiedPackageName, PackageDepAtom::ConstPointer> virtual_to_real;
+
+ 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;
+
+ RepositoryProvidesInterface::ProvidesCollection::ConstPointer provides(
+ (*r)->provides_interface->provided_packages());
+ for (RepositoryProvidesInterface::ProvidesCollection::Iterator p(provides->begin()),
+ p_end(provides->end()) ; p != p_end ; ++p)
+ virtual_to_real.insert(std::make_pair(p->virtual_name, PackageDepAtom::Pointer(
+ new PackageDepAtom(stringify(p->provided_by_name)))));
+ }
+
+ for (PackageDatabase::RepositoryIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ; r != r_end ; ++r)
+ {
+ if (! (*r)->virtuals_interface)
+ continue;
+
+ RepositoryVirtualsInterface::VirtualsCollection::ConstPointer virtuals(
+ (*r)->virtuals_interface->virtual_packages());
+ for (RepositoryVirtualsInterface::VirtualsCollection::Iterator v(virtuals->begin()),
+ v_end(virtuals->end()) ; v != v_end ; ++v)
+ virtual_to_real.insert(std::make_pair(v->virtual_name, v->provided_by_atom));
+ }
+
+ /* Populate our _imp->entries. */
+ for (std::map<QualifiedPackageName, PackageDepAtom::ConstPointer>::const_iterator
+ v(virtual_to_real.begin()), v_end(virtual_to_real.end()) ; v != v_end ; ++v)
+ {
+ PackageDatabaseEntryCollection::ConstPointer matches(_imp->env->package_database()->query(v->second,
+ is_uninstalled_only));
+
+ if (matches->empty())
+ Log::get_instance()->message(ll_warning, lc_context, "No packages matching '"
+ + stringify(*v->second) + "' for virtual '"
+ + stringify(v->first));
+
+ for (PackageDatabaseEntryCollection::Iterator m(matches->begin()), m_end(matches->end()) ;
+ m != m_end ; ++m)
+ {
+ _imp->entries.push_back(VREntry::create()
+ .virtual_name(v->first)
+ .version(m->version)
+ .provided_by_name(m->name)
+ .provided_by_repository(m->repository));
+ }
+ }
+
+ std::sort(_imp->entries.begin(), _imp->entries.end());
+
+ _imp->has_entries = true;
+}
+
+CountedPtr<Repository>
+VirtualsRepository::make_virtuals_repository(
+ const Environment * const env,
+ const PackageDatabase * const,
+ AssociativeCollection<std::string, std::string>::ConstPointer)
+{
+ return CountedPtr<Repository>(new VirtualsRepository(env));
+}
+
+bool
+VirtualsRepository::do_query_repository_masks(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+bool
+VirtualsRepository::do_query_profile_masks(const QualifiedPackageName &,
+ const VersionSpec &) const
+{
+ return false;
+}
+
+VersionMetadata::ConstPointer
+VirtualsRepository::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())));
+
+ Log::get_instance()->message(ll_debug, lc_no_context, "VirtualsRepository::do_version_metadata("
+ + stringify(q) + ", " + stringify(v) + ") lookup using '"
+ + stringify(p.first->virtual_name) + "', '" + stringify(p.first->version) + "', '"
+ + stringify(p.first->provided_by_name) + "', '" + stringify(p.first->provided_by_repository) + "'");
+
+ return _imp->env->package_database()->fetch_repository(
+ p.first->provided_by_repository)->virtuals_interface->virtual_package_version_metadata(
+ RepositoryVirtualsEntry::create()
+ .virtual_name(p.first->virtual_name)
+ .provided_by_atom(PackageDepAtom::Pointer(new PackageDepAtom(p.first->provided_by_name))), v);
+}
+
+bool
+VirtualsRepository::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;
+}
+
+VersionSpecCollection::ConstPointer
+VirtualsRepository::do_version_specs(const QualifiedPackageName & q) const
+{
+ if (q.category.data() != "virtual")
+ return VersionSpecCollection::Pointer(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()));
+
+ VersionSpecCollection::Pointer result(new VersionSpecCollection::Concrete);
+ for ( ; p.first != p.second ; ++p.first)
+ result->insert(p.first->version);
+
+ return result;
+}
+
+QualifiedPackageNameCollection::ConstPointer
+VirtualsRepository::do_package_names(const CategoryNamePart & c) const
+{
+ if (c.data() != "virtual")
+ return QualifiedPackageNameCollection::Pointer(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()));
+
+
+ QualifiedPackageNameCollection::Pointer 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;
+}
+
+CategoryNamePartCollection::ConstPointer
+VirtualsRepository::do_category_names() const
+{
+ need_entries();
+
+ CategoryNamePartCollection::Pointer result(new CategoryNamePartCollection::Concrete);
+#if 0
+ /// \todo: in theory, this can be a lot lot lot faster
+ for (std::vector<VREntry>::const_iterator p(_imp->entries.begin()), p_end(_imp->entries.end()) ;
+ p != p_end ; ++p)
+ result->insert(p->virtual_name.category);
+#else
+ fast_unique_copy(_imp->entries.begin(), _imp->entries.end(),
+ transform_inserter(result->inserter(), EntriesCategoryExtractor()),
+ EntriesCategoryComparator());
+#endif
+
+ return result;
+}
+
+bool
+VirtualsRepository::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
+VirtualsRepository::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
+VirtualsRepository::do_is_licence(const std::string &) const
+{
+ return false;
+}
+
+void
+VirtualsRepository::invalidate() const
+{
+ _imp->has_entries = false;
+ _imp->entries.clear();
+}
+
+void
+VirtualsRepository::do_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const
+{
+}
+
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility push(default)
+#endif
+namespace
+{
+ const RepositoryMaker::RegisterMaker register_virtuals_repository PALUDIS_ATTRIBUTE((used)) (
+ "virtuals", &VirtualsRepository::make_virtuals_repository);
+}
+#ifdef PALUDIS_ENABLE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
diff --git a/0.8.0/paludis/repositories/virtuals/virtuals_repository.hh b/0.8.0/paludis/repositories/virtuals/virtuals_repository.hh
new file mode 100644
index 0000000..10cb520
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/virtuals_repository.hh
@@ -0,0 +1,87 @@
+/* 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_VIRTUALS_VIRTUALS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_VIRTUALS_VIRTUALS_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE VirtualsRepository :
+ public Repository,
+ public RepositoryInstallableInterface,
+ public RepositoryMaskInterface,
+ private PrivateImplementationPattern<VirtualsRepository>
+ {
+ 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 VersionMetadata::ConstPointer do_version_metadata(
+ const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual bool do_has_version(const QualifiedPackageName &,
+ const VersionSpec &) const;
+
+ virtual VersionSpecCollection::ConstPointer do_version_specs(
+ const QualifiedPackageName &) const;
+
+ virtual QualifiedPackageNameCollection::ConstPointer do_package_names(
+ const CategoryNamePart &) const;
+
+ virtual CategoryNamePartCollection::ConstPointer 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_install(const QualifiedPackageName &, const VersionSpec &,
+ const InstallOptions &) const;
+
+ public:
+ VirtualsRepository(const Environment * const env);
+
+ virtual ~VirtualsRepository();
+
+ static CountedPtr<Repository> make_virtuals_repository(
+ const Environment * const env,
+ const PackageDatabase * const db,
+ AssociativeCollection<std::string, std::string>::ConstPointer);
+
+ virtual void invalidate() const;
+
+ virtual bool can_be_favourite_repository() const
+ {
+ return false;
+ }
+
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/virtuals/vr_entry.cc b/0.8.0/paludis/repositories/virtuals/vr_entry.cc
new file mode 100644
index 0000000..30b142f
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/vr_entry.cc
@@ -0,0 +1,26 @@
+/* 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 "vr_entry.hh"
+#include <paludis/util/compare.hh>
+
+using namespace paludis;
+
+#include <paludis/repositories/virtuals/vr_entry-sr.cc>
+
diff --git a/0.8.0/paludis/repositories/virtuals/vr_entry.hh b/0.8.0/paludis/repositories/virtuals/vr_entry.hh
new file mode 100644
index 0000000..86206fd
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/vr_entry.hh
@@ -0,0 +1,119 @@
+/* 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_VIRTUALS_VR_ENTRY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_VIRTUALS_VR_ENTRY_HH 1
+
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/package_database.hh>
+#include <paludis/environment.hh>
+
+namespace paludis
+{
+
+#include <paludis/repositories/virtuals/vr_entry-sr.hh>
+
+ /**
+ * Sort ordering for _imp->entries for an InstalledVirtualsRepository.
+ */
+ struct EntriesComparator
+ {
+ PackageDatabase::ConstPointer const db;
+
+ EntriesComparator(PackageDatabase::ConstPointer const d) :
+ db(d)
+ {
+ }
+
+ bool
+ operator() (const VREntry & a, const VREntry & b) const
+ {
+ switch (a.compare(b))
+ {
+ case -1:
+ return true;
+
+ case 1:
+ return false;
+ }
+
+ if (a.provided_by_repository != b.provided_by_repository)
+ {
+ // not a bug
+ if (a.provided_by_repository == db->better_repository(a.provided_by_repository,
+ b.provided_by_repository))
+ return true;
+ return false;
+ }
+
+ return a.provided_by_name > b.provided_by_name; // not a bug either
+ }
+ };
+
+ /**
+ * Comparison on name only for an VREntry.
+ */
+ struct EntriesNameComparator
+ {
+ bool
+ operator() (const VREntry & a, const VREntry & b) const
+ {
+ return a.virtual_name < b.virtual_name;
+ }
+ };
+
+ /**
+ * Extract only the name for an VREntry.
+ */
+ struct EntriesNameExtractor
+ {
+ QualifiedPackageName
+ operator() (const VREntry & a) const
+ {
+ return a.virtual_name;
+ }
+ };
+
+ /**
+ * Comparison on category name only for an VREntry.
+ */
+ struct EntriesCategoryComparator
+ {
+ bool
+ operator() (const VREntry & a, const VREntry & b) const
+ {
+ return a.virtual_name.category < b.virtual_name.category;
+ }
+ };
+
+ /**
+ * Extract only the category name for an VREntry.
+ */
+ struct EntriesCategoryExtractor
+ {
+ CategoryNamePart
+ operator() (const VREntry & a) const
+ {
+ return a.virtual_name.category;
+ }
+ };
+}
+
+#endif
diff --git a/0.8.0/paludis/repositories/virtuals/vr_entry.sr b/0.8.0/paludis/repositories/virtuals/vr_entry.sr
new file mode 100644
index 0000000..eba905f
--- /dev/null
+++ b/0.8.0/paludis/repositories/virtuals/vr_entry.sr
@@ -0,0 +1,16 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_VREntry()
+{
+ key virtual_name QualifiedPackageName
+ key version VersionSpec
+ key provided_by_name QualifiedPackageName
+ key provided_by_repository RepositoryName
+
+ comparison_operators all virtual_name version
+
+ allow_named_args
+}
+
+