aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-08-12 17:02:26 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-08-12 17:02:26 +0000
commita4b62d4570134df17bae2ea195d0693187904687 (patch)
tree7e820a3f89ab6a13281213df322509566fa0ae8b
parenta613b16bb6af396ab612c294e5f8c8874bbac515 (diff)
downloadpaludis-a4b62d4570134df17bae2ea195d0693187904687.tar.gz
paludis-a4b62d4570134df17bae2ea195d0693187904687.tar.xz
More QA work
-rw-r--r--paludis/repositories/e/Makefile.am9
-rw-r--r--paludis/repositories/e/e_repository.cc76
-rw-r--r--paludis/repositories/e/qa/Makefile.am28
-rw-r--r--paludis/repositories/e/qa/qa.cc63
-rw-r--r--paludis/repositories/e/qa/qa_controller.hh2
-rw-r--r--paludis/repositories/e/qa/spec_keys.cc127
-rw-r--r--paludis/repositories/e/qa/spec_keys_TEST.cc20
-rw-r--r--paludis/repositories/e/qa/spec_keys_pds_blacklist.DEPEND.conf2
-rw-r--r--paludis/repositories/e/qa/spec_keys_pds_blacklist.PDEPEND.conf0
-rw-r--r--paludis/repositories/e/qa/spec_keys_pds_blacklist.PROVIDE.conf1
-rw-r--r--paludis/repositories/e/qa/spec_keys_pds_blacklist.RDEPEND.conf16
-rw-r--r--paludis/repositories/e/qa/spec_keys_pds_blacklist.SDEPEND.conf0
-rw-r--r--paludis/repositories/e/qa/test_extras.cc26
13 files changed, 332 insertions, 38 deletions
diff --git a/paludis/repositories/e/Makefile.am b/paludis/repositories/e/Makefile.am
index 9e01e2c..fa10e1f 100644
--- a/paludis/repositories/e/Makefile.am
+++ b/paludis/repositories/e/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = eapis ebuild qa .
+SUBDIRS = eapis ebuild . qa
CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
DISTCLEANFILES = \
glsa-sr.hh glsa-sr.cc \
@@ -132,14 +132,7 @@ libpaludiserepository_la_SOURCES = \
vdb_unmerger.cc \
$(paludis_repositories_e_include_HEADERS)
-if ENABLE_QA
-libpaludiserepository_la_LIBADD_IF_QA = $(top_builddir)/paludis/repositories/e/qa/libpaludiserepositoryqa.la
-else
-libpaludiserepository_la_LIBADD_IF_QA =
-endif
-
libpaludiserepository_la_LIBADD = \
- $(libpaludiserepository_la_LIBADD_IF_QA) \
$(top_builddir)/paludis/repositories/libpaludisrepositories.la \
$(top_builddir)/paludis/merger/libpaludismerger.la \
$(top_builddir)/paludis/digests/libpaludisdigests.la \
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index 9a9906d..fabb382 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -50,6 +50,7 @@
#include <paludis/syncer.hh>
#include <paludis/action.hh>
#include <paludis/mask.hh>
+#include <paludis/qa.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/iterator.hh>
@@ -86,6 +87,11 @@
#include <strings.h>
#include <ctype.h>
+#include <dlfcn.h>
+#include <stdint.h>
+
+#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
+
/** \file
* Implementation of ERepository.
*
@@ -999,6 +1005,38 @@ ERepository::perform_hook(const Hook & hook) const
return HookResult(0, "");
}
+#ifdef ENABLE_QA
+namespace
+{
+ struct LibQAHandle
+ {
+ Mutex mutex;
+ void * handle;
+ void (* qa_checks_handle)(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepository> &,
+ const QACheckProperties & ignore_if,
+ const QACheckProperties & ignore_unless,
+ const QAMessageLevel minimum_level,
+ QAReporter & reporter,
+ const FSEntry & dir);
+
+ LibQAHandle() :
+ handle(0),
+ qa_checks_handle(0)
+ {
+ }
+
+ ~LibQAHandle()
+ {
+ if (0 != handle)
+ dlclose(handle);
+ }
+
+ } libqahandle;
+}
+#endif
+
void
ERepository::check_qa(
QAReporter & reporter,
@@ -1011,16 +1049,38 @@ ERepository::check_qa(
#ifdef ENABLE_QA
Context c("When performing QA checks for '" + stringify(dir) + "':");
- erepository::QAController controller(
- _imp->params.environment,
- shared_from_this(),
- ignore_if,
- ignore_unless,
- minimum_level,
- reporter);
+ {
+ Lock lock(libqahandle.mutex);
+
+ if (0 == libqahandle.handle)
+ libqahandle.handle = dlopen("libpaludiserepositoryqa.so", RTLD_NOW | RTLD_GLOBAL);
+ if (0 == libqahandle.handle)
+ {
+ reporter.message(QAMessage(dir, qaml_severe, "check_qa", "Got error '" + stringify(dlerror) +
+ "' when dlopen(libpaludisqa.so)"));
+ return;
+ }
- controller.run();
+ if (0 == libqahandle.qa_checks_handle)
+ libqahandle.qa_checks_handle = STUPID_CAST(void (*)(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepository> &,
+ const QACheckProperties &,
+ const QACheckProperties &,
+ const QAMessageLevel,
+ QAReporter &,
+ const FSEntry &),
+ dlsym(libqahandle.handle, "check_qa"));
+ if (0 == libqahandle.qa_checks_handle)
+ {
+ reporter.message(QAMessage(dir, qaml_severe, "check_qa", "Got error '" + stringify(dlerror) +
+ "' when dlsym(libpaludisqa.so, \"check_qa\")"));
+ return;
+ }
+ }
+ (*libqahandle.qa_checks_handle)(_imp->params.environment, shared_from_this(), ignore_if, ignore_unless,
+ minimum_level, reporter, dir);
#endif
}
diff --git a/paludis/repositories/e/qa/Makefile.am b/paludis/repositories/e/qa/Makefile.am
index 07d799a..06d54c8 100644
--- a/paludis/repositories/e/qa/Makefile.am
+++ b/paludis/repositories/e/qa/Makefile.am
@@ -12,6 +12,15 @@ DEFS = \
if ENABLE_QA
+paludis_qa_datadir = $(datadir)/paludis/qa/
+
+paludis_qa_data_DATA = \
+ spec_keys_pds_blacklist.DEPEND.conf \
+ spec_keys_pds_blacklist.RDEPEND.conf \
+ spec_keys_pds_blacklist.PDEPEND.conf \
+ spec_keys_pds_blacklist.SDEPEND.conf \
+ spec_keys_pds_blacklist.PROVIDE.conf
+
paludis_repositories_e_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/repositories/e/
paludis_repositories_e_include_HEADERS = \
eapi_supported.hh \
@@ -23,9 +32,10 @@ paludis_repositories_e_include_HEADERS = \
short_description_key.hh \
stray_files.hh
-noinst_LTLIBRARIES = libpaludiserepositoryqa.la
+lib_LTLIBRARIES = libpaludiserepositoryqa.la
libpaludiserepositoryqa_la_SOURCES = \
+ qa.cc \
eapi_supported.cc \
homepage_key.cc \
qa_checks.cc \
@@ -36,9 +46,15 @@ libpaludiserepositoryqa_la_SOURCES = \
stray_files.cc \
$(paludis_repositories_e_include_HEADERS)
+libpaludiserepositoryqa_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+libpaludiserepositoryqa_la_LIBADD = \
+ $(top_builddir)/paludis/repositories/e/libpaludiserepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la
+
endif
-EXTRA_DIST =
+EXTRA_DIST = $(paludis_qa_data_DATA) test_extras.cc
BUILT_SOURCES =
check_SCRIPTS =
@@ -48,6 +64,7 @@ TESTS_ENVIRONMENT = env \
PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/e/ebuild/`" \
PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/repositories/e/eapis/" \
+ PALUDIS_QA_DATA_DIR="$(top_srcdir)/paludis/repositories/e/qa/" \
PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
PALUDIS_DISTRIBUTION="gentoo" \
PALUDIS_SKIP_CONFIG="yes" \
@@ -67,8 +84,9 @@ TESTS = \
check_PROGRAMS = $(TESTS)
spec_keys_TEST_SOURCES = spec_keys_TEST.cc
-spec_keys_TEST_LDFLAGS = \
+spec_keys_TEST_LDADD = \
libpaludiserepositoryqa.la \
+ test_extras.o \
$(top_builddir)/paludis/repositories/e/libpaludiserepository.la \
$(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.la \
$(top_builddir)/paludis/util/libpaludisutil.la \
@@ -78,9 +96,11 @@ spec_keys_TEST_LDFLAGS = \
$(top_builddir)/test/libtest.a
stray_files_TEST_SOURCES = stray_files_TEST.cc
-stray_files_TEST_LDFLAGS = \
+stray_files_TEST_LDADD = \
libpaludiserepositoryqa.la \
+ test_extras.o \
$(top_builddir)/paludis/repositories/e/libpaludiserepository.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.la \
$(top_builddir)/paludis/util/libpaludisutil.la \
$(top_builddir)/paludis/util/test_extras.o \
$(top_builddir)/paludis/libpaludis.la \
diff --git a/paludis/repositories/e/qa/qa.cc b/paludis/repositories/e/qa/qa.cc
new file mode 100644
index 0000000..d69b27d
--- /dev/null
+++ b/paludis/repositories/e/qa/qa.cc
@@ -0,0 +1,63 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/e/qa/qa_controller.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/qa-fwd.hh>
+
+using namespace paludis;
+
+namespace paludis
+{
+ class RepositoryMaker;
+ class ERepository;
+}
+
+extern "C"
+{
+ void PALUDIS_VISIBLE register_repositories(paludis::RepositoryMaker * maker);
+ void PALUDIS_VISIBLE check_qa(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepository> &,
+ const QACheckProperties &,
+ const QACheckProperties &,
+ const QAMessageLevel,
+ QAReporter &,
+ const FSEntry &);
+}
+
+void register_repositories(paludis::RepositoryMaker *)
+{
+}
+
+void check_qa(
+ const Environment * const env,
+ const tr1::shared_ptr<const ERepository> & repo,
+ const QACheckProperties & ignore_if,
+ const QACheckProperties & ignore_unless,
+ const QAMessageLevel minimum_level,
+ QAReporter & reporter,
+ const FSEntry &)
+{
+ erepository::QAController controller(env, repo, ignore_if, ignore_unless, minimum_level, reporter);
+ controller.run();
+}
+
diff --git a/paludis/repositories/e/qa/qa_controller.hh b/paludis/repositories/e/qa/qa_controller.hh
index d47483d..9d75092 100644
--- a/paludis/repositories/e/qa/qa_controller.hh
+++ b/paludis/repositories/e/qa/qa_controller.hh
@@ -38,7 +38,7 @@ namespace paludis
namespace erepository
{
- class QAController :
+ class PALUDIS_VISIBLE QAController :
private PrivateImplementationPattern<QAController>
{
private:
diff --git a/paludis/repositories/e/qa/spec_keys.cc b/paludis/repositories/e/qa/spec_keys.cc
index 53dbe82..0f54810 100644
--- a/paludis/repositories/e/qa/spec_keys.cc
+++ b/paludis/repositories/e/qa/spec_keys.cc
@@ -22,21 +22,64 @@
#include <paludis/metadata_key.hh>
#include <paludis/qa.hh>
#include <paludis/dep_spec.hh>
+#include <paludis/config_file.hh>
#include <paludis/repositories/e/eapi.hh>
#include <paludis/repositories/e/e_repository_id.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/save.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/system.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/iterator.hh>
#include <paludis/util/parallel_for_each.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
#include <algorithm>
+#include <map>
using namespace paludis;
using namespace paludis::erepository;
namespace
{
+ struct SpecKeysBlacklist :
+ InstantiationPolicy<SpecKeysBlacklist, instantiation_method::SingletonTag>
+ {
+ Mutex mutex;
+ std::map<std::string, const tr1::shared_ptr<const QualifiedPackageNameSet> > map;
+
+ const tr1::shared_ptr<const QualifiedPackageNameSet> blacklist(const std::string & s)
+ {
+ Lock lock(mutex);
+ std::map<std::string, const tr1::shared_ptr<const QualifiedPackageNameSet> >::const_iterator i(map.find(s));
+ if (map.end() != i)
+ return i->second;
+ else
+ {
+ Context context("When loading spec_keys PackageDepSpec blacklist '" + s + "':");
+
+ tr1::shared_ptr<QualifiedPackageNameSet> r(new QualifiedPackageNameSet);
+ FSEntry f(FSEntry(getenv_with_default("PALUDIS_QA_DATA_DIR",
+ stringify(FSEntry(DATADIR) / "paludis" / "qa")))
+ / ("spec_keys_pds_blacklist." + s + ".conf"));
+
+ if (f.exists())
+ {
+ LineConfigFile ff(f, LineConfigFileOptions());
+ std::copy(ff.begin(), ff.end(), create_inserter<QualifiedPackageName>(r->inserter()));
+ }
+ else
+ Log::get_instance()->message(ll_warning, lc_context) << "Blacklist data file '" << f << "' does not exist";
+
+ map.insert(std::make_pair(s, r));
+ return r;
+ }
+ }
+ };
+
struct Checker :
ConstVisitor<GenericSpecTree>
{
@@ -45,6 +88,8 @@ namespace
const tr1::shared_ptr<const PackageID> & id;
const MetadataKey & key;
const std::string name;
+ const tr1::shared_ptr<const QualifiedPackageNameSet> pds_blacklist;
+
unsigned level;
bool child_of_any;
@@ -53,19 +98,27 @@ namespace
QAReporter & r,
const tr1::shared_ptr<const PackageID> & i,
const MetadataKey & k,
- const std::string & n) :
+ const std::string & n,
+ const tr1::shared_ptr<const QualifiedPackageNameSet> p) :
entry(f),
reporter(r),
id(i),
key(k),
name(n),
+ pds_blacklist(p),
level(0),
child_of_any(false)
{
}
- void visit_leaf(const PackageDepSpec &)
+ void visit_leaf(const PackageDepSpec & p)
{
+ if (pds_blacklist && p.package_ptr())
+ {
+ if (pds_blacklist->end() != pds_blacklist->find(*p.package_ptr()))
+ reporter.message(QAMessage(entry, qaml_normal, name, "Package specification '" + stringify(*p.package_ptr())
+ + "' blacklisted in spec key '" + stringify(key.raw_name()) + "'"));
+ }
}
void visit_leaf(const BlockDepSpec & b)
@@ -203,37 +256,77 @@ namespace
void visit(const MetadataSpecTreeKey<URISpecTree> & k)
{
- Context context("When visiting metadata key '" + k.raw_name() + "':");
- Checker c(entry, reporter, id, k, name);
- k.value()->accept(c);
+ try
+ {
+ Context context("When visiting metadata key '" + k.raw_name() + "':");
+ Checker c(entry, reporter, id, k, name, tr1::shared_ptr<const QualifiedPackageNameSet>());
+ k.value()->accept(c);
+ }
+ catch (const Exception & e)
+ {
+ reporter.message(QAMessage(entry, qaml_severe, name, "Caught exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ") when handling key '" + k.raw_name() + "'"));
+ }
}
void visit(const MetadataSpecTreeKey<LicenseSpecTree> & k)
{
- Context context("When visiting metadata key '" + k.raw_name() + "':");
- Checker c(entry, reporter, id, k, name);
- k.value()->accept(c);
+ try
+ {
+ Context context("When visiting metadata key '" + k.raw_name() + "':");
+ Checker c(entry, reporter, id, k, name, tr1::shared_ptr<const QualifiedPackageNameSet>());
+ k.value()->accept(c);
+ }
+ catch (const Exception & e)
+ {
+ reporter.message(QAMessage(entry, qaml_severe, name, "Caught exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ") when handling key '" + k.raw_name() + "'"));
+ }
}
void visit(const MetadataSpecTreeKey<DependencySpecTree> & k)
{
- Context context("When visiting metadata key '" + k.raw_name() + "':");
- Checker c(entry, reporter, id, k, name);
- k.value()->accept(c);
+ try
+ {
+ Context context("When visiting metadata key '" + k.raw_name() + "':");
+ Checker c(entry, reporter, id, k, name, SpecKeysBlacklist::get_instance()->blacklist(k.raw_name()));
+ k.value()->accept(c);
+ }
+ catch (const Exception & e)
+ {
+ reporter.message(QAMessage(entry, qaml_severe, name, "Caught exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ") when handling key '" + k.raw_name() + "'"));
+ }
}
void visit(const MetadataSpecTreeKey<ProvideSpecTree> & k)
{
- Context context("When visiting metadata key '" + k.raw_name() + "':");
- Checker c(entry, reporter, id, k, name);
- k.value()->accept(c);
+ try
+ {
+ Context context("When visiting metadata key '" + k.raw_name() + "':");
+ Checker c(entry, reporter, id, k, name, SpecKeysBlacklist::get_instance()->blacklist(k.raw_name()));
+ k.value()->accept(c);
+ }
+ catch (const Exception & e)
+ {
+ reporter.message(QAMessage(entry, qaml_severe, name, "Caught exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ") when handling key '" + k.raw_name() + "'"));
+ }
}
void visit(const MetadataSpecTreeKey<RestrictSpecTree> & k)
{
- Context context("When visiting metadata key '" + k.raw_name() + "':");
- Checker c(entry, reporter, id, k, name);
- k.value()->accept(c);
+ try
+ {
+ Context context("When visiting metadata key '" + k.raw_name() + "':");
+ Checker c(entry, reporter, id, k, name, tr1::shared_ptr<const QualifiedPackageNameSet>());
+ k.value()->accept(c);
+ }
+ catch (const Exception & e)
+ {
+ reporter.message(QAMessage(entry, qaml_severe, name, "Caught exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ") when handling key '" + k.raw_name() + "'"));
+ }
}
};
}
diff --git a/paludis/repositories/e/qa/spec_keys_TEST.cc b/paludis/repositories/e/qa/spec_keys_TEST.cc
index f3d502e..9ede1b5 100644
--- a/paludis/repositories/e/qa/spec_keys_TEST.cc
+++ b/paludis/repositories/e/qa/spec_keys_TEST.cc
@@ -158,5 +158,25 @@ namespace test_cases
TEST_CHECK_EQUAL(r.count, 1u);
}
} test_any_block;
+
+ struct DeprecatedTest : TestCase
+ {
+ DeprecatedTest() : TestCase("deprecated") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo")));
+ env.package_database()->add_repository(1, repo);
+ repo->add_version("virtual", "libc", "1");
+
+ tr1::shared_ptr<FakePackageID> id(repo->add_version("cat", "pkg", "1"));
+ id->build_dependencies_key()->set_from_string("virtual/libc");
+
+ TestReporter r;
+ TEST_CHECK(spec_keys_check(FSEntry("/var/empty"), r, id, "spec keys"));
+ TEST_CHECK_EQUAL(r.count, 1u);
+ }
+ } test_deprecated;
}
diff --git a/paludis/repositories/e/qa/spec_keys_pds_blacklist.DEPEND.conf b/paludis/repositories/e/qa/spec_keys_pds_blacklist.DEPEND.conf
new file mode 100644
index 0000000..cb217d8
--- /dev/null
+++ b/paludis/repositories/e/qa/spec_keys_pds_blacklist.DEPEND.conf
@@ -0,0 +1,2 @@
+sys-apps/portage
+virtual/libc
diff --git a/paludis/repositories/e/qa/spec_keys_pds_blacklist.PDEPEND.conf b/paludis/repositories/e/qa/spec_keys_pds_blacklist.PDEPEND.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paludis/repositories/e/qa/spec_keys_pds_blacklist.PDEPEND.conf
diff --git a/paludis/repositories/e/qa/spec_keys_pds_blacklist.PROVIDE.conf b/paludis/repositories/e/qa/spec_keys_pds_blacklist.PROVIDE.conf
new file mode 100644
index 0000000..a9715b8
--- /dev/null
+++ b/paludis/repositories/e/qa/spec_keys_pds_blacklist.PROVIDE.conf
@@ -0,0 +1 @@
+virtual/libc
diff --git a/paludis/repositories/e/qa/spec_keys_pds_blacklist.RDEPEND.conf b/paludis/repositories/e/qa/spec_keys_pds_blacklist.RDEPEND.conf
new file mode 100644
index 0000000..6eea495
--- /dev/null
+++ b/paludis/repositories/e/qa/spec_keys_pds_blacklist.RDEPEND.conf
@@ -0,0 +1,16 @@
+app-arch/cabextract
+app-arch/rpm2targz
+app-arch/unzip
+app-doc/doxygen
+dev-util/pkgconfig
+dev-util/yacc
+media-gfx/ebdftopcf
+sys-devel/autoconf
+sys-devel/automake
+sys-devel/bison
+sys-devel/flex
+sys-devel/gettext
+sys-devel/libtool
+sys-devel/patch
+x11-apps/bdftopcf
+x11-misc/imake
diff --git a/paludis/repositories/e/qa/spec_keys_pds_blacklist.SDEPEND.conf b/paludis/repositories/e/qa/spec_keys_pds_blacklist.SDEPEND.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/paludis/repositories/e/qa/spec_keys_pds_blacklist.SDEPEND.conf
diff --git a/paludis/repositories/e/qa/test_extras.cc b/paludis/repositories/e/qa/test_extras.cc
new file mode 100644
index 0000000..23a617d
--- /dev/null
+++ b/paludis/repositories/e/qa/test_extras.cc
@@ -0,0 +1,26 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/e/e_repository.hh>
+
+void work_around_annoying_linker_bug(const paludis::ERepository & repo)
+{
+ bool PALUDIS_ATTRIBUTE((unused)) b(repo.layout()->eapi_ebuild_suffix());
+}
+