aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-11-11 22:31:10 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-11-12 17:09:47 +0000
commit0507e963d7ed9300fd561fd9c24fe870bfac61a2 (patch)
treefc57eea1fa6ef7f5ca1eb5236c0c3c08b60627a2
parent634aa07ea0e8fa854308f81db2f72af1fca907bd (diff)
downloadpaludis-0507e963d7ed9300fd561fd9c24fe870bfac61a2.tar.gz
paludis-0507e963d7ed9300fd561fd9c24fe870bfac61a2.tar.xz
Add metadata.xml support.
-rw-r--r--configure.ac21
-rw-r--r--paludis/repositories/e/Makefile.am10
-rw-r--r--paludis/repositories/e/e_installed_repository_id.cc4
-rw-r--r--paludis/repositories/e/e_key.cc39
-rw-r--r--paludis/repositories/e/e_key.hh5
-rw-r--r--paludis/repositories/e/ebuild_id.cc21
-rw-r--r--paludis/repositories/e/glsa.cc75
-rw-r--r--paludis/repositories/e/metadata_xml.cc92
-rw-r--r--paludis/repositories/e/metadata_xml.hh74
-rw-r--r--paludis/repositories/e/xml_things.cc327
-rw-r--r--paludis/repositories/e/xml_things.hh17
-rw-r--r--paludis/repositories/e/xml_things_handle.cc161
-rw-r--r--paludis/repositories/e/xml_things_handle.hh57
-rw-r--r--paludis/util/hashes.cc10
-rw-r--r--paludis/util/hashes.hh8
15 files changed, 785 insertions, 136 deletions
diff --git a/configure.ac b/configure.ac
index 3aa6b52..877ac96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -865,14 +865,13 @@ AM_CONDITIONAL([HAVE_HTMLTIDY], test "x$HAVE_HTMLTIDY" = "xyes")
dnl {{{ check for whether to build qa stuff
AC_MSG_CHECKING([whether to build QA tools])
AC_ARG_ENABLE([qa],
- AS_HELP_STRING([--enable-qa], [Build QA things (needs pcre++, libxml2)]),
+ AS_HELP_STRING([--enable-qa], [Build QA things (needs pcre++)]),
[ENABLE_QA=$enableval
AC_MSG_RESULT([$enableval])],
[ENABLE_QA=no
AC_MSG_RESULT([no])])
if test x"$ENABLE_QA" = "xyes" ; then
need_pcrepp_check=yes
- need_xml_check=yes
AC_DEFINE([ENABLE_RUBY_QA], [1], [Enable QA support in ruby])
AC_DEFINE([ENABLE_QA], [1], [Build QA things])
fi
@@ -896,6 +895,22 @@ AC_SUBST([ENABLE_GLSA])
AM_CONDITIONAL([ENABLE_GLSA], test "x$ENABLE_GLSA" = "xyes")
dnl }}}
+dnl {{{ check for whether to build metadata.xml stuff
+AC_MSG_CHECKING([whether to build metadata.xml support])
+AC_ARG_ENABLE([metadata-xml],
+ AS_HELP_STRING([--enable-metadata-xml], [Build metadata.xml things (needs libxml2)]),
+ [ENABLE_METADATA_XML=$enableval
+ AC_MSG_RESULT([$enableval])],
+ [ENABLE_METADATA_XML=no
+ AC_MSG_RESULT([no])])
+if test x"$ENABLE_METADATA_XML" = "xyes" ; then
+ need_xml_check=yes
+ AC_DEFINE([ENABLE_METADATA_XML], [1], [Build metadata.xml support])
+fi
+AC_SUBST([ENABLE_METADATA_XML])
+AM_CONDITIONAL([ENABLE_METADATA_XML], test "x$ENABLE_METADATA_XML" = "xyes")
+dnl }}}
+
dnl {{{ colourschemes
AC_MSG_CHECKING([whether we like pink])
AC_ARG_ENABLE([pink],
@@ -1366,7 +1381,7 @@ dnl {{{ libxml2 check
NEED_XML=$need_xml_check
if test "x$need_xml_check" = "xyes" ; then
PKG_CHECK_MODULES(LIBXML2DEPS, [libxml-2.0 >= 2.6], [],
- [AC_MSG_ERROR([libxml2 (http://xmlsoft.org/) is required if --enable-qa or --enable-glsa is used])])
+ [AC_MSG_ERROR([libxml2 (http://xmlsoft.org/) is required if --enable-metadata-xml or --enable-glsa is used])])
AC_SUBST(LIBXML2DEPS_CFLAGS)
AC_SUBST(LIBXML2DEPS_LIBS)
fi
diff --git a/paludis/repositories/e/Makefile.am b/paludis/repositories/e/Makefile.am
index aafb05c..40f2985 100644
--- a/paludis/repositories/e/Makefile.am
+++ b/paludis/repositories/e/Makefile.am
@@ -23,9 +23,11 @@ paludis_repositories_libdir = $(libdir)/paludis/repositories
paludis_repositories_lib_LTLIBRARIES = libpaludiserepository_@PALUDIS_PC_SLOT@.la
if ENABLE_GLSA
-
lib_LTLIBRARIES = libpaludiserepositoryxmlthings_@PALUDIS_PC_SLOT@.la
-
+else
+if ENABLE_METADATA_XML
+lib_LTLIBRARIES = libpaludiserepositoryxmlthings_@PALUDIS_PC_SLOT@.la
+endif
endif
paludis_repositories_e_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/repositories/e/
@@ -82,12 +84,14 @@ paludis_repositories_e_include_HEADERS = \
layout.hh \
manifest2_entry-sr.hh \
manifest2_reader.hh \
+ metadata_xml.hh \
myoption.hh \
myoptions_requirements_verifier.hh \
pipe_command_handler.hh \
source_uri_finder.hh \
traditional_layout.hh \
use_desc.hh \
+ xml_things_handle.hh \
vdb_contents_tokeniser.hh \
vdb_id.hh \
vdb_merger.hh \
@@ -136,6 +140,7 @@ libpaludiserepository_@PALUDIS_PC_SLOT@_la_SOURCES = \
glsa.cc \
layout.cc \
manifest2_reader.cc \
+ metadata_xml.cc \
myoption.cc \
myoptions_requirements_verifier.cc \
pipe_command_handler.cc \
@@ -143,6 +148,7 @@ libpaludiserepository_@PALUDIS_PC_SLOT@_la_SOURCES = \
source_uri_finder.cc \
traditional_layout.cc \
use_desc.cc \
+ xml_things_handle.cc \
vdb_id.cc \
vdb_merger.cc \
vdb_repository.cc \
diff --git a/paludis/repositories/e/e_installed_repository_id.cc b/paludis/repositories/e/e_installed_repository_id.cc
index 4100d9d..54c3ca1 100644
--- a/paludis/repositories/e/e_installed_repository_id.cc
+++ b/paludis/repositories/e/e_installed_repository_id.cc
@@ -428,10 +428,10 @@ EInstalledRepositoryID::need_keys_added() const
if (_imp->eapi->supported())
_imp->choices.reset(new EChoicesKey(_imp->environment, shared_from_this(), "PALUDIS_CHOICES",
_imp->eapi->supported()->ebuild_environment_variables()->description_choices(),
- mkt_normal, std::tr1::shared_ptr<const ERepository>()));
+ mkt_normal, make_null_shared_ptr(), make_null_shared_ptr()));
else
_imp->choices.reset(new EChoicesKey(_imp->environment, shared_from_this(), "PALUDIS_CHOICES", "Choices", mkt_normal,
- std::tr1::shared_ptr<const ERepository>()));
+ make_null_shared_ptr(), make_null_shared_ptr()));
add_metadata_key(_imp->choices);
diff --git a/paludis/repositories/e/e_key.cc b/paludis/repositories/e/e_key.cc
index 7f01a9e..10f7e1b 100644
--- a/paludis/repositories/e/e_key.cc
+++ b/paludis/repositories/e/e_key.cc
@@ -35,6 +35,7 @@
#include <paludis/util/log.hh>
#include <paludis/util/mutex.hh>
#include <paludis/util/set.hh>
+#include <paludis/util/map.hh>
#include <paludis/util/join.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/visitor_cast.hh>
@@ -880,12 +881,15 @@ namespace paludis
const Environment * const env;
const std::tr1::shared_ptr<const ERepositoryID> id;
const std::tr1::shared_ptr<const ERepository> maybe_e_repository;
+ const std::tr1::shared_ptr<const Map<ChoiceNameWithPrefix, std::string> > maybe_descriptions;
Implementation(const Environment * const e, const std::tr1::shared_ptr<const ERepositoryID> & i,
- const std::tr1::shared_ptr<const ERepository> & p) :
+ const std::tr1::shared_ptr<const ERepository> & p,
+ const std::tr1::shared_ptr<const Map<ChoiceNameWithPrefix, std::string> > & d) :
env(e),
id(i),
- maybe_e_repository(p)
+ maybe_e_repository(p),
+ maybe_descriptions(d)
{
}
};
@@ -895,9 +899,10 @@ EChoicesKey::EChoicesKey(
const Environment * const e,
const std::tr1::shared_ptr<const ERepositoryID> & i,
const std::string & r, const std::string & h, const MetadataKeyType t,
- const std::tr1::shared_ptr<const ERepository> & p) :
+ const std::tr1::shared_ptr<const ERepository> & p,
+ const std::tr1::shared_ptr<const Map<ChoiceNameWithPrefix, std::string> > & d) :
MetadataValueKey<std::tr1::shared_ptr<const Choices> > (r, h, t),
- PrivateImplementationPattern<EChoicesKey>(new Implementation<EChoicesKey>(e, i, p)),
+ PrivateImplementationPattern<EChoicesKey>(new Implementation<EChoicesKey>(e, i, p, d)),
_imp(PrivateImplementationPattern<EChoicesKey>::_imp)
{
}
@@ -1019,11 +1024,19 @@ namespace
}
return id->make_choice_value(choice, v->first, s, b, description, false);
}
-}
-#include <iostream>
-#include <paludis/util/join.hh>
-#include <paludis/util/member_iterator-impl.hh>
+ std::string get_maybe_description(const std::tr1::shared_ptr<const Map<ChoiceNameWithPrefix, std::string> > & m,
+ const ChoiceNameWithPrefix & k)
+ {
+ if (m)
+ {
+ Map<ChoiceNameWithPrefix, std::string>::ConstIterator i(m->find(k));
+ if (i != m->end())
+ return i->second;
+ }
+ return "";
+ }
+}
const std::tr1::shared_ptr<const Choices>
EChoicesKey::value() const
@@ -1125,7 +1138,9 @@ EChoicesKey::value() const
i_values.insert(flag);
else
{
- std::tr1::shared_ptr<const ChoiceValue> choice(_imp->id->make_choice_value(use, UnprefixedChoiceName(stringify(flag.first)), flag.second, true, "", false));
+ std::tr1::shared_ptr<const ChoiceValue> choice(_imp->id->make_choice_value(
+ use, UnprefixedChoiceName(stringify(flag.first)), flag.second, true,
+ get_maybe_description(_imp->maybe_descriptions, flag.first), false));
if (stringify(flag.first) == _imp->id->eapi()->supported()->choices_options()->fancy_test_flag())
{
/* have to add this right at the end, after build_options is there */
@@ -1162,7 +1177,8 @@ EChoicesKey::value() const
/* don't need to worry */
}
else
- use->add(_imp->id->make_choice_value(use, UnprefixedChoiceName(stringify(flag.first)), flag.second, false, "", false));
+ use->add(_imp->id->make_choice_value(use, UnprefixedChoiceName(stringify(flag.first)), flag.second, false,
+ get_maybe_description(_imp->maybe_descriptions, flag.first), false));
}
}
}
@@ -1227,7 +1243,8 @@ EChoicesKey::value() const
{
std::map<ChoiceNameWithPrefix, Tribool>::const_iterator i(i_values.find(ChoiceNameWithPrefix(lower_u + delim + stringify(*v))));
if (i_values.end() != i)
- exp->add(_imp->id->make_choice_value(exp, *v, i->second, true, "", false));
+ exp->add(_imp->id->make_choice_value(exp, *v, i->second, true,
+ get_maybe_description(_imp->maybe_descriptions, i->first), false));
else
exp->add(_imp->id->make_choice_value(exp, *v, indeterminate, false, "", false));
}
diff --git a/paludis/repositories/e/e_key.hh b/paludis/repositories/e/e_key.hh
index a5958ad..b676bb0 100644
--- a/paludis/repositories/e/e_key.hh
+++ b/paludis/repositories/e/e_key.hh
@@ -23,6 +23,8 @@
#include <paludis/metadata_key.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/set.hh>
+#include <paludis/util/map-fwd.hh>
+#include <paludis/choice-fwd.hh>
namespace paludis
{
@@ -307,7 +309,8 @@ namespace paludis
const std::string &,
const std::string &,
const MetadataKeyType,
- const std::tr1::shared_ptr<const ERepository> & maybe_profile);
+ const std::tr1::shared_ptr<const ERepository> & maybe_profile,
+ const std::tr1::shared_ptr<const Map<ChoiceNameWithPrefix, std::string> > & maybe_descriptions);
~EChoicesKey();
diff --git a/paludis/repositories/e/ebuild_id.cc b/paludis/repositories/e/ebuild_id.cc
index 44db25e..5e90908 100644
--- a/paludis/repositories/e/ebuild_id.cc
+++ b/paludis/repositories/e/ebuild_id.cc
@@ -28,6 +28,7 @@
#include <paludis/repositories/e/eapi.hh>
#include <paludis/repositories/e/manifest2_reader.hh>
#include <paludis/repositories/e/e_choice_value.hh>
+#include <paludis/repositories/e/metadata_xml.hh>
#include <paludis/name.hh>
#include <paludis/version_spec.hh>
@@ -280,6 +281,7 @@ EbuildID::need_keys_added() const
std::tr1::static_pointer_cast<const ERepository>(repository())->profile()->profile_masked(*this), mkt_internal));
add_metadata_key(_imp->profile_mask);
+ std::tr1::shared_ptr<const Map<ChoiceNameWithPrefix, std::string> > maybe_use_descriptions;
if (_imp->eapi->supported())
{
_imp->raw_use_expand = make_shared_ptr(new LiteralMetadataStringSetKey(
@@ -292,15 +294,30 @@ EbuildID::need_keys_added() const
_imp->eapi->supported()->ebuild_metadata_variables()->use_expand_hidden().description(),
mkt_internal,
std::tr1::static_pointer_cast<const ERepository>(repository())->profile()->use_expand_hidden()));
+
+ std::tr1::shared_ptr<const MetadataXML> m(MetadataXMLPool::get_instance()->metadata_if_exists(
+ _imp->fs_location->value().dirname() / "metadata.xml"));
+ if (m)
+ {
+ if (! m->long_description().empty())
+ add_metadata_key(_imp->long_description = make_shared_ptr(new LiteralMetadataValueKey<std::string>("long_description",
+ "Long Description", mkt_normal, m->long_description())));
+ if (! m->herds()->empty())
+ add_metadata_key(make_shared_ptr(new LiteralMetadataStringSequenceKey("herds", "Herds", mkt_normal, m->herds())));
+ if (! m->maintainers()->empty())
+ add_metadata_key(make_shared_ptr(new LiteralMetadataStringSequenceKey("maintainers", "Maintainers", mkt_normal, m->maintainers())));
+ maybe_use_descriptions = m->uses();
+ }
}
if (_imp->eapi->supported())
_imp->choices.reset(new EChoicesKey(_imp->environment, shared_from_this(), "PALUDIS_CHOICES",
_imp->eapi->supported()->ebuild_environment_variables()->description_choices(),
- mkt_normal, std::tr1::static_pointer_cast<const ERepository>(repository())));
+ mkt_normal, std::tr1::static_pointer_cast<const ERepository>(repository()),
+ maybe_use_descriptions));
else
_imp->choices.reset(new EChoicesKey(_imp->environment, shared_from_this(), "PALUDIS_CHOICES", "Choices", mkt_normal,
- std::tr1::static_pointer_cast<const ERepository>(repository())));
+ std::tr1::static_pointer_cast<const ERepository>(repository()), maybe_use_descriptions));
add_metadata_key(_imp->choices);
}
diff --git a/paludis/repositories/e/glsa.cc b/paludis/repositories/e/glsa.cc
index 66dec5c..fb425b8 100644
--- a/paludis/repositories/e/glsa.cc
+++ b/paludis/repositories/e/glsa.cc
@@ -17,7 +17,8 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "glsa.hh"
+#include <paludis/repositories/e/glsa.hh>
+#include <paludis/repositories/e/xml_things_handle.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/mutex.hh>
@@ -29,8 +30,6 @@
#include <stdint.h>
#include "config.h"
-#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
-
using namespace paludis;
template class WrappedForwardIterator<GLSAPackage::ArchsConstIteratorTag, const std::string>;
@@ -39,10 +38,6 @@ template class WrappedForwardIterator<GLSA::PackagesConstIteratorTag, const GLSA
#include "glsa-sr.cc"
-#ifdef MONOLITHIC
-# include <paludis/repositories/e/xml_things.hh>
-#endif
-
namespace paludis
{
template<>
@@ -188,73 +183,19 @@ GLSA::title() const
return _imp->title;
}
-#ifndef MONOLITHIC
-
-namespace
-{
- struct LibXMLHandle
- {
- Mutex mutex;
- void * handle;
- std::tr1::shared_ptr<GLSA> (* create_glsa_from_xml_file_handle)(const std::string &);
-
- LibXMLHandle() :
- handle(0),
- create_glsa_from_xml_file_handle(0)
- {
- }
-
- ~LibXMLHandle()
- {
- if (0 != handle)
- dlclose(handle);
- }
-
- } libxmlhandle;
-}
-
-#endif
-
std::tr1::shared_ptr<GLSA>
GLSA::create_from_xml_file(const std::string & filename)
{
-#if ENABLE_GLSA
-# ifdef MONOLITHIC
-
-# else
+ if (! erepository::XMLThingsHandle::get_instance()->available())
{
- Lock lock(libxmlhandle.mutex);
-
- if (0 == libxmlhandle.handle)
- libxmlhandle.handle = dlopen(("libpaludiserepositoryxmlthings_" + stringify(PALUDIS_PC_SLOT) + ".so").c_str(),
- RTLD_NOW | RTLD_GLOBAL);
- if (0 == libxmlhandle.handle)
- throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' due to error '"
- + stringify(dlerror()) + "' when dlopen(libpaludiserepositoryxmlthings.so)");
-
- if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
- libxmlhandle.create_glsa_from_xml_file_handle = STUPID_CAST(std::tr1::shared_ptr<GLSA> (*)(const std::string &),
- dlsym(libxmlhandle.handle, "create_glsa_from_xml_file"));
- if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
- throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' due to error '"
- + stringify(dlerror()) + "' when dlsym(libpaludisgentoorepositoryxmlthings.so, create_glsa_from_xml_file)");
- }
-
-# endif
+#ifdef ENABLE_GLSA
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' because your XML libraries are unusable");
#else
-# ifndef MONOLITHIC
- /* avoid noreturn warning */
- if (0 == libxmlhandle.handle)
- throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' because Paludis was built "
- "without GLSA support");
-# endif
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' because GLSA support was not enabled at compile time");
#endif
+ }
-#ifdef MONOLITHIC
- return create_glsa_from_xml_file(filename);
-#else
- return (*libxmlhandle.create_glsa_from_xml_file_handle)(filename);
-#endif
+ return erepository::XMLThingsHandle::get_instance()->create_glsa_from_xml_file()(filename);
}
GLSAError::GLSAError(const std::string & msg, const std::string & filename) throw () :
diff --git a/paludis/repositories/e/metadata_xml.cc b/paludis/repositories/e/metadata_xml.cc
new file mode 100644
index 0000000..f69d4a1
--- /dev/null
+++ b/paludis/repositories/e/metadata_xml.cc
@@ -0,0 +1,92 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public 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/metadata_xml.hh>
+#include <paludis/repositories/e/xml_things_handle.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
+#include <paludis/util/map-impl.hh>
+#include <paludis/util/validated.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/log.hh>
+#include <paludis/literal_metadata_key.hh>
+#include <paludis/choice.hh>
+#include <tr1/unordered_map>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+typedef std::tr1::unordered_map<FSEntry, std::tr1::shared_ptr<MetadataXML>, Hash<FSEntry> > Store;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<MetadataXMLPool>
+ {
+ mutable Mutex mutex;
+ mutable Store store;
+ };
+}
+
+MetadataXMLPool::MetadataXMLPool() :
+ PrivateImplementationPattern<MetadataXMLPool>(new Implementation<MetadataXMLPool>)
+{
+}
+
+MetadataXMLPool::~MetadataXMLPool()
+{
+}
+
+const std::tr1::shared_ptr<const MetadataXML>
+MetadataXMLPool::metadata_if_exists(const FSEntry & f) const
+{
+ Context context("When handling metadata.xml file '" + stringify(f) + "':");
+
+ FSEntry f_real(f.realpath_if_exists());
+ Lock lock(_imp->mutex);
+ Store::const_iterator i(_imp->store.find(f_real));
+ if (i != _imp->store.end())
+ return i->second;
+ else
+ {
+ std::tr1::shared_ptr<MetadataXML> metadata_xml;
+ if (f_real.is_regular_file_or_symlink_to_regular_file())
+ {
+ try
+ {
+ if (XMLThingsHandle::get_instance()->available())
+ metadata_xml = XMLThingsHandle::get_instance()->create_metadata_xml_from_xml_file()(f);
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message("e.metadata_xml.bad", ll_warning, lc_context) << "Got exception '"
+ << e.message() << "' (" << e.what() << "), ignoring metadata.xml file '" << f_real << "'";
+ }
+ }
+ return _imp->store.insert(std::make_pair(f_real, metadata_xml)).first->second;
+ }
+}
+
+template class Map<ChoiceNameWithPrefix, std::string>;
+template class PrivateImplementationPattern<MetadataXMLPool>;
+template class InstantiationPolicy<MetadataXMLPool, instantiation_method::SingletonTag>;
+
diff --git a/paludis/repositories/e/metadata_xml.hh b/paludis/repositories/e/metadata_xml.hh
new file mode 100644
index 0000000..0558f58
--- /dev/null
+++ b/paludis/repositories/e/metadata_xml.hh
@@ -0,0 +1,74 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public 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_E_METADATA_XML_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_METADATA_XML_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/sequence-fwd.hh>
+#include <paludis/util/map-fwd.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/choice-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace n
+ {
+ struct herds;
+ struct long_description;
+ struct maintainers;
+ struct uses;
+ }
+
+ namespace erepository
+ {
+ struct MetadataXML
+ {
+ NamedValue<n::herds, std::tr1::shared_ptr<Sequence<std::string> > > herds;
+ NamedValue<n::long_description, std::string> long_description;
+ NamedValue<n::maintainers, std::tr1::shared_ptr<Sequence<std::string> > > maintainers;
+ NamedValue<n::uses, std::tr1::shared_ptr<Map<ChoiceNameWithPrefix, std::string> > > uses;
+ };
+
+ class PALUDIS_VISIBLE MetadataXMLPool :
+ private PrivateImplementationPattern<MetadataXMLPool>,
+ public InstantiationPolicy<MetadataXMLPool, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<MetadataXMLPool, instantiation_method::SingletonTag>;
+
+ private:
+ MetadataXMLPool();
+ ~MetadataXMLPool();
+
+ public:
+ const std::tr1::shared_ptr<const MetadataXML> metadata_if_exists(const FSEntry &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<erepository::MetadataXMLPool>;
+ extern template class InstantiationPolicy<erepository::MetadataXMLPool, instantiation_method::SingletonTag>;
+#endif
+}
+
+#endif
diff --git a/paludis/repositories/e/xml_things.cc b/paludis/repositories/e/xml_things.cc
index e34576f..e08d43a 100644
--- a/paludis/repositories/e/xml_things.cc
+++ b/paludis/repositories/e/xml_things.cc
@@ -17,43 +17,128 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-#include <paludis/repositories/e/glsa.hh>
-#include <paludis/util/tokeniser.hh>
-#include <paludis/util/join.hh>
+#include <paludis/repositories/e/xml_things.hh>
#include <paludis/util/config_file.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/validated.hh>
+#include <paludis/choice.hh>
#include <set>
-#include <list>
-using namespace paludis;
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
-extern "C"
-{
- std::tr1::shared_ptr<GLSA> PALUDIS_VISIBLE create_glsa_from_xml_file(const std::string &);
-}
+using namespace paludis;
namespace
{
- std::string retarded_libxml_string_to_string(const xmlChar * const s)
+ class PALUDIS_VISIBLE XMLError :
+ public Exception
{
- return s ? stringify(reinterpret_cast<const char *>(s)) : "";
+ public:
+ XMLError(const std::string & w) throw () :
+ Exception("XML error: " + w)
+ {
+ }
+ };
+
+ const xmlChar * stupid_libxml_string(const char * const s)
+ {
+ return reinterpret_cast<const xmlChar *>(s);
+ }
+
+ std::string unstupid_libxml_string(const xmlChar * const s)
+ {
+ return s ? std::string(reinterpret_cast<const char *>(s)) : "";
}
- std::string normalise(const std::string & s)
+ bool is_space(const char c)
{
- std::list<std::string> words;
- tokenise_whitespace(s, std::back_inserter(words));
- return join(words.begin(), words.end(), " ");
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
- class Handler
+ std::string fix_whitespace(const std::string & s)
+ {
+ std::string t;
+ t.reserve(s.length());
+
+ std::string::size_type p(0), p_end(s.length());
+
+ while (p != p_end && is_space(s[p]))
+ ++p;
+
+ while (p_end > p && is_space(s[p_end - 1]))
+ --p_end;
+
+ while (p != p_end)
+ {
+ while (p != p_end && ! is_space(s[p]))
+ t.append(1, s[p++]);
+
+ if (p != p_end)
+ t.append(1, ' ');
+
+ while (p != p_end && is_space(s[p]))
+ ++p;
+ }
+
+ return t;
+ }
+
+ std::string extract_child_text(const xmlNode * const node)
+ {
+ switch (node->type)
+ {
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ return fix_whitespace(unstupid_libxml_string(node->content));
+
+ default:
+ throw XMLError("Node not an XML_TEXT_NODE or XML_CDATA_SECTION_NODE");
+ };
+ }
+
+ std::string extract_children_text(const std::tr1::shared_ptr<const xmlXPathObject> & object)
+ {
+ std::string result;
+ bool need_space(false);
+
+ for (int j = 0 ; j != object->nodesetval->nodeNr ; ++j)
+ {
+ std::string item(extract_child_text(object->nodesetval->nodeTab[j]));
+ if (! item.empty())
+ {
+ if (need_space)
+ result.append(" ");
+ result.append(item);
+ need_space = true;
+ }
+ }
+
+ return result;
+ }
+
+ template <typename T_>
+ std::tr1::shared_ptr<T_> manage_libxml_ptr(T_ * const p, void (* d) (T_ * const))
+ {
+ if (! p)
+ throw XMLError("libxml2 returned null for " + std::string(__PRETTY_FUNCTION__));
+ return std::tr1::shared_ptr<T_>(p, d);
+ }
+
+#ifdef ENABLE_GLSA
+ class GLSAHandler
{
private:
std::tr1::shared_ptr<GLSA> _glsa;
public:
- Handler() :
+ GLSAHandler() :
_glsa(new GLSA)
{
}
@@ -64,10 +149,9 @@ namespace
{
if (a->type == XML_ATTRIBUTE_NODE)
{
- std::string name(retarded_libxml_string_to_string(a->name));
+ std::string name(unstupid_libxml_string(a->name));
if (name == "id")
- _glsa->set_id(normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
- a->xmlChildrenNode, 1))));
+ _glsa->set_id(fix_whitespace(unstupid_libxml_string(xmlNodeListGetString(doc, a->xmlChildrenNode, 1))));
}
}
}
@@ -78,9 +162,9 @@ namespace
{
if (a->type == XML_ATTRIBUTE_NODE)
{
- std::string name(retarded_libxml_string_to_string(a->name));
+ std::string name(unstupid_libxml_string(a->name));
if (name == "name")
- str = normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
+ str = fix_whitespace(unstupid_libxml_string(xmlNodeListGetString(doc,
a->xmlChildrenNode, 1)));
}
}
@@ -92,11 +176,11 @@ namespace
{
if (a->type == XML_ATTRIBUTE_NODE)
{
- std::string name(retarded_libxml_string_to_string(a->name));
+ std::string name(unstupid_libxml_string(a->name));
if (name == "arch")
{
std::set<std::string> archs;
- tokenise_whitespace(retarded_libxml_string_to_string(xmlNodeListGetString(doc, a->xmlChildrenNode, 1)),
+ tokenise_whitespace(unstupid_libxml_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()) ;
@@ -113,10 +197,9 @@ namespace
{
if (a->type == XML_ATTRIBUTE_NODE)
{
- std::string name(retarded_libxml_string_to_string(a->name));
+ std::string name(unstupid_libxml_string(a->name));
if (name == "range")
- op = normalise(retarded_libxml_string_to_string(xmlNodeListGetString(doc,
- a->xmlChildrenNode, 1)));
+ op = fix_whitespace(unstupid_libxml_string(xmlNodeListGetString(doc, a->xmlChildrenNode, 1)));
}
}
}
@@ -127,13 +210,12 @@ namespace
{
if (n->type == XML_ELEMENT_NODE)
{
- std::string name(retarded_libxml_string_to_string(n->name));
+ std::string name(unstupid_libxml_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))));
+ std::string version(fix_whitespace(unstupid_libxml_string(xmlNodeListGetString(doc, n->xmlChildrenNode, 1))));
((*pkg).*(name == "unaffected" ? &GLSAPackage::add_unaffected : &GLSAPackage::add_vulnerable))
(GLSARange::create().op(op).version(version));
}
@@ -152,15 +234,14 @@ namespace
{
if (n->type == XML_ELEMENT_NODE)
{
- std::string name(retarded_libxml_string_to_string(n->name));
+ std::string name(unstupid_libxml_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))));
+ _glsa->set_title(fix_whitespace(unstupid_libxml_string(xmlNodeListGetString(doc, n->xmlChildrenNode, 1))));
else if (name == "package")
{
std::string m;
@@ -184,21 +265,179 @@ namespace
return _glsa;
}
};
+#endif
+
}
+#ifdef ENABLE_GLSA
+
std::tr1::shared_ptr<GLSA>
-create_glsa_from_xml_file(const std::string & filename)
+paludis_xml_things_create_glsa_from_xml_file(const std::string & filename)
+{
+ try
+ {
+ std::tr1::shared_ptr<xmlDoc> doc(manage_libxml_ptr(xmlParseFile(filename.c_str()), &xmlFreeDoc));
+
+ GLSAHandler h;
+ h.handle_node(doc.get(), xmlDocGetRootElement(doc.get()));
+ return h.glsa();
+ }
+ catch (const XMLError & e)
+ {
+ throw GLSAError(e.message(), filename);
+ }
+}
+
+#endif
+
+#ifdef ENABLE_METADATA_XML
+
+std::tr1::shared_ptr<erepository::MetadataXML>
+paludis_xml_things_create_metadata_xml_from_xml_file(const FSEntry & filename)
{
- std::tr1::shared_ptr<xmlDoc> xml_doc(xmlReadFile(filename.c_str(), 0, 0), &xmlFreeDoc);
- if (! xml_doc)
- throw GLSAError("Could not parse GLSA", filename);
+ std::tr1::shared_ptr<erepository::MetadataXML> result(new erepository::MetadataXML(
+ make_named_values<erepository::MetadataXML>(
+ value_for<n::herds>(make_shared_ptr(new Sequence<std::string>)),
+ value_for<n::long_description>(""),
+ value_for<n::maintainers>(make_shared_ptr(new Sequence<std::string>)),
+ value_for<n::uses>(make_shared_ptr(new Map<ChoiceNameWithPrefix, std::string>))
+ )));
+
+ std::tr1::shared_ptr<xmlDoc> doc(manage_libxml_ptr(xmlParseFile(stringify(filename).c_str()), &xmlFreeDoc));
- Handler h;
- h.handle_node(xml_doc.get(), xmlDocGetRootElement(xml_doc.get()));
- return h.glsa();
+ std::tr1::shared_ptr<xmlXPathContext>
+ doc_context(manage_libxml_ptr(xmlXPathNewContext(doc.get()), &xmlXPathFreeContext)),
+ sub_context(manage_libxml_ptr(xmlXPathNewContext(doc.get()), &xmlXPathFreeContext)),
+ text_context(manage_libxml_ptr(xmlXPathNewContext(doc.get()), &xmlXPathFreeContext));
+
+ std::tr1::shared_ptr<xmlXPathObject>
+ herd_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string(
+ "//pkgmetadata/herd"), doc_context.get()), xmlXPathFreeObject)),
+ maintainer_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string(
+ "//pkgmetadata/maintainer"), doc_context.get()), xmlXPathFreeObject)),
+ use_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string(
+ "//pkgmetadata/use"), doc_context.get()), xmlXPathFreeObject));
+
+ for (int i = 0 ; i != herd_object->nodesetval->nodeNr ; ++i)
+ {
+ text_context->node = herd_object->nodesetval->nodeTab[i];
+ std::tr1::shared_ptr<xmlXPathObject> text_object(manage_libxml_ptr(
+ xmlXPathEvalExpression(stupid_libxml_string("descendant::text()"),
+ text_context.get()), xmlXPathFreeObject));
+
+ result->herds()->push_back(extract_children_text(text_object));
+ }
+
+ for (int i = 0 ; i != maintainer_object->nodesetval->nodeNr ; ++i)
+ {
+ std::string name, email;
+
+ sub_context->node = maintainer_object->nodesetval->nodeTab[i];
+ std::tr1::shared_ptr<xmlXPathObject>
+ name_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string("./name[position()=1]"),
+ sub_context.get()), xmlXPathFreeObject)),
+ email_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string("./email[position()=1]"),
+ sub_context.get()), xmlXPathFreeObject));
+
+ if (name_object->nodesetval->nodeNr)
+ {
+ text_context->node = name_object->nodesetval->nodeTab[0];
+ std::tr1::shared_ptr<xmlXPathObject> text_object(manage_libxml_ptr(
+ xmlXPathEvalExpression(stupid_libxml_string("descendant::text()"),
+ text_context.get()), xmlXPathFreeObject));
+ name = extract_children_text(text_object);
+ }
+
+ if (email_object->nodesetval->nodeNr)
+ {
+ text_context->node = email_object->nodesetval->nodeTab[0];
+ std::tr1::shared_ptr<xmlXPathObject> text_object(manage_libxml_ptr(
+ xmlXPathEvalExpression(stupid_libxml_string("descendant::text()"),
+ text_context.get()), xmlXPathFreeObject));
+ email = extract_children_text(text_object);
+ }
+
+ if ((! name.empty()) || (! email.empty()))
+ {
+ std::string p;
+ if (! name.empty())
+ {
+ p = name;
+ if (! email.empty())
+ p = p + " <" + email + ">";
+ }
+ else
+ p = email;
+
+ result->maintainers()->push_back(email);
+ }
+ }
+
+ for (int i = 0 ; i != use_object->nodesetval->nodeNr ; ++i)
+ {
+ sub_context->node = use_object->nodesetval->nodeTab[i];
+ std::tr1::shared_ptr<xmlXPathObject> flag_object(
+ manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string("./flag[@name]"),
+ sub_context.get()), xmlXPathFreeObject));
+
+ for (int k = 0 ; k != flag_object->nodesetval->nodeNr ; ++k)
+ {
+ text_context->node = flag_object->nodesetval->nodeTab[k];
+ std::tr1::shared_ptr<xmlXPathObject>
+ text_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string("descendant::text()"),
+ text_context.get()), xmlXPathFreeObject)),
+ name_object(manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string("@name"),
+ text_context.get()), xmlXPathFreeObject));
+
+ std::string desc(extract_children_text(text_object));
+ std::string name;
+
+ if (! name_object->nodesetval->nodeNr)
+ throw XMLError("no name attribute");
+
+ if (name_object->nodesetval->nodeTab[0]->type != XML_ATTRIBUTE_NODE)
+ throw XMLError("Node not an XML_ATTRIBUTE_NODE");
+
+ name.append(unstupid_libxml_string(xmlNodeListGetString(doc.get(),
+ name_object->nodesetval->nodeTab[0]->xmlChildrenNode, 1)));
+
+ result->uses()->insert(ChoiceNameWithPrefix(name), desc);
+ }
+ }
+
+ std::tr1::shared_ptr<xmlXPathObject> longdesc_object;
+ longdesc_object = manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string(
+ "//pkgmetadata/longdescription[@lang=\"en\"]"), doc_context.get()), xmlXPathFreeObject);
+ if (0 == longdesc_object->nodesetval->nodeNr)
+ longdesc_object = manage_libxml_ptr(xmlXPathEvalExpression(stupid_libxml_string(
+ "//pkgmetadata/longdescription[not(@lang)]"), doc_context.get()), xmlXPathFreeObject);
+
+ for (int i = 0 ; i != longdesc_object->nodesetval->nodeNr ; ++i)
+ {
+ text_context->node = longdesc_object->nodesetval->nodeTab[i];
+ std::tr1::shared_ptr<xmlXPathObject> text_object(manage_libxml_ptr(
+ xmlXPathEvalExpression(stupid_libxml_string("descendant::text()"),
+ text_context.get()), xmlXPathFreeObject));
+
+ result->long_description() = extract_children_text(text_object);
+ }
+
+ return result;
+}
+
+#endif
+
+void
+paludis_xml_things_init()
+{
+ xmlInitParser();
}
-#ifndef MONOLITHIC
+void
+paludis_xml_things_cleanup()
+{
+ xmlCleanupParser();
+}
namespace paludis
{
@@ -209,5 +448,3 @@ extern "C" void PALUDIS_VISIBLE paludis_initialise_repository_so(paludis::Reposi
{
}
-#endif
-
diff --git a/paludis/repositories/e/xml_things.hh b/paludis/repositories/e/xml_things.hh
index 486cfd5..50ee0b2 100644
--- a/paludis/repositories/e/xml_things.hh
+++ b/paludis/repositories/e/xml_things.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -21,10 +21,23 @@
#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_XML_THINGS_HH 1
#include <paludis/repositories/e/glsa.hh>
+#include <paludis/repositories/e/metadata_xml.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include "config.h"
extern "C"
{
- GLSA::Pointer PALUDIS_VISIBLE create_glsa_from_xml_file(const std::string &);
+ void paludis_xml_things_init() PALUDIS_VISIBLE;
+ void paludis_xml_things_cleanup() PALUDIS_VISIBLE;
+
+#if ENABLE_GLSA
+ std::tr1::shared_ptr<paludis::GLSA> PALUDIS_VISIBLE paludis_xml_things_create_glsa_from_xml_file(const std::string &);
+#endif
+
+#if ENABLE_METADATA_XML
+ std::tr1::shared_ptr<paludis::erepository::MetadataXML> PALUDIS_VISIBLE paludis_xml_things_create_metadata_xml_from_xml_file(
+ const paludis::FSEntry &) PALUDIS_ATTRIBUTE((warn_unused_result));
+#endif
}
#endif
diff --git a/paludis/repositories/e/xml_things_handle.cc b/paludis/repositories/e/xml_things_handle.cc
new file mode 100644
index 0000000..b8db73f
--- /dev/null
+++ b/paludis/repositories/e/xml_things_handle.cc
@@ -0,0 +1,161 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public 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/xml_things_handle.hh>
+#include <paludis/about.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
+#include "config.h"
+#include <dlfcn.h>
+#include <stdint.h>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
+
+namespace paludis
+{
+ template <>
+ struct Implementation<XMLThingsHandle>
+ {
+ void * handle;
+
+ bool available;
+ std::tr1::shared_ptr<GLSA> (* create_glsa_from_xml_file) (const std::string &);
+ std::tr1::shared_ptr<MetadataXML> (* create_metadata_xml_from_xml_file) (const FSEntry &);
+ void (* init) ();
+ void (* cleanup) ();
+
+ Implementation() :
+ handle(0),
+ available(false),
+ create_glsa_from_xml_file(0),
+ create_metadata_xml_from_xml_file(0),
+ init(0),
+ cleanup(0)
+ {
+#if defined(ENABLE_GLSA) || defined(ENABLE_METADATA_XML)
+ available = true;
+
+ handle = ::dlopen(("libpaludiserepositoryxmlthings_" + stringify(PALUDIS_PC_SLOT) + ".so").c_str(), RTLD_NOW | RTLD_GLOBAL);
+ if (! handle)
+ {
+ Log::get_instance()->message("e.xml_things.dlopen_failed", ll_warning, lc_context) << "Got error '"
+ << ::dlerror() << "' from dlopen for XML things";
+ available = false;
+ }
+
+ if (available)
+ {
+ init = STUPID_CAST(void (*)(), ::dlsym(handle, "paludis_xml_things_init"));
+ if (! init)
+ {
+ Log::get_instance()->message("e.xml_things.dlsym_failed", ll_warning, lc_context) << "Got error '"
+ << ::dlerror() << "' from dlsym for init";
+ available = false;
+ }
+ }
+
+ if (available)
+ {
+ cleanup = STUPID_CAST(void (*)(), ::dlsym(handle, "paludis_xml_things_cleanup"));
+ if (! cleanup)
+ {
+ Log::get_instance()->message("e.xml_things.dlsym_failed", ll_warning, lc_context) << "Got error '"
+ << ::dlerror() << "' from dlsym for cleanup";
+ available = false;
+ }
+ }
+
+# ifdef ENABLE_GLSA
+ if (available)
+ {
+ create_glsa_from_xml_file = STUPID_CAST(std::tr1::shared_ptr<GLSA> (*)(const std::string &),
+ ::dlsym(handle, "paludis_xml_things_create_glsa_from_xml_file"));
+ if (! create_glsa_from_xml_file)
+ {
+ Log::get_instance()->message("e.xml_things.dlsym_failed", ll_warning, lc_context) << "Got error '"
+ << ::dlerror() << "' from dlsym for GLSA things";
+ available = false;
+ }
+ }
+# endif
+
+# ifdef ENABLE_METADATA_XML
+ if (available)
+ {
+ create_metadata_xml_from_xml_file = STUPID_CAST(std::tr1::shared_ptr<MetadataXML> (*)(const FSEntry &),
+ ::dlsym(handle, "paludis_xml_things_create_metadata_xml_from_xml_file"));
+ if (! create_metadata_xml_from_xml_file)
+ {
+ Log::get_instance()->message("e.xml_things.dlsym_failed", ll_warning, lc_context) << "Got error '"
+ << ::dlerror() << "' from dlsym for metadata.xml things";
+ available = false;
+ }
+ }
+# endif
+
+ if (available)
+ {
+ init();
+ }
+#endif
+ }
+ };
+}
+
+XMLThingsHandle::XMLThingsHandle() :
+ PrivateImplementationPattern<XMLThingsHandle>(new Implementation<XMLThingsHandle>)
+{
+}
+
+XMLThingsHandle::~XMLThingsHandle()
+{
+ if (0 != _imp->cleanup)
+ _imp->cleanup();
+
+ // don't dlclose, gcc does something dumb on cleanup
+ // if (0 != _imp->handle)
+ // ::dlclose(_imp->handle);
+}
+
+bool
+XMLThingsHandle::available() const
+{
+ return _imp->available;
+}
+
+std::tr1::shared_ptr<GLSA>
+(* XMLThingsHandle::create_glsa_from_xml_file() const) (const std::string &)
+{
+ return _imp->create_glsa_from_xml_file;
+}
+
+std::tr1::shared_ptr<MetadataXML>
+(* XMLThingsHandle::create_metadata_xml_from_xml_file() const) (const FSEntry &)
+{
+ return _imp->create_metadata_xml_from_xml_file;
+}
+
+template class PrivateImplementationPattern<XMLThingsHandle>;
+template class InstantiationPolicy<XMLThingsHandle, instantiation_method::SingletonTag>;
+
diff --git a/paludis/repositories/e/xml_things_handle.hh b/paludis/repositories/e/xml_things_handle.hh
new file mode 100644
index 0000000..35ab7aa
--- /dev/null
+++ b/paludis/repositories/e/xml_things_handle.hh
@@ -0,0 +1,57 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public 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_E_XML_THINGS_HANDLE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_XML_THINGS_HANDLE_HH 1
+
+#include <paludis/repositories/e/glsa.hh>
+#include <paludis/repositories/e/metadata_xml.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class PALUDIS_VISIBLE XMLThingsHandle :
+ private PrivateImplementationPattern<XMLThingsHandle>,
+ public InstantiationPolicy<XMLThingsHandle, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<XMLThingsHandle, instantiation_method::SingletonTag>;
+
+ private:
+ XMLThingsHandle();
+ ~XMLThingsHandle();
+
+ public:
+ bool available() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::tr1::shared_ptr<GLSA> (* create_glsa_from_xml_file() const) (const std::string &);
+ std::tr1::shared_ptr<MetadataXML> (* create_metadata_xml_from_xml_file() const) (const FSEntry &);
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<erepository::XMLThingsHandle>;
+ extern template class InstantiationPolicy<erepository::XMLThingsHandle, instantiation_method::SingletonTag>;
+#endif
+}
+
+#endif
diff --git a/paludis/util/hashes.cc b/paludis/util/hashes.cc
index 6a600fe..fb22995 100644
--- a/paludis/util/hashes.cc
+++ b/paludis/util/hashes.cc
@@ -17,8 +17,10 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <string>
#include <paludis/util/hashes.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/stringify.hh>
+#include <string>
#include <tr1/functional>
using namespace paludis;
@@ -29,3 +31,9 @@ Hash<std::string>::operator() (const std::string & s) const
return std::tr1::hash<std::string>()(s);
}
+std::size_t
+Hash<FSEntry>::operator() (const FSEntry & s) const
+{
+ return std::tr1::hash<std::string>()(stringify(s));
+}
+
diff --git a/paludis/util/hashes.hh b/paludis/util/hashes.hh
index 6b29fde..2291022 100644
--- a/paludis/util/hashes.hh
+++ b/paludis/util/hashes.hh
@@ -22,8 +22,10 @@
#include <paludis/util/attributes.hh>
#include <paludis/util/validated-fwd.hh>
+#include <paludis/util/fs_entry-fwd.hh>
#include <cstddef>
#include <utility>
+#include <string>
#include <tr1/type_traits>
#include <tr1/memory>
@@ -66,6 +68,12 @@ namespace paludis
std::size_t operator() (const std::string &) const PALUDIS_ATTRIBUTE((warn_unused_result));
};
+ template <>
+ struct PALUDIS_VISIBLE Hash<FSEntry>
+ {
+ std::size_t operator() (const FSEntry &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
template <typename T_, typename U_>
struct Hash<std::pair<T_, U_> >
{