aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-08-26 09:37:16 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2010-08-26 15:56:04 +0100
commitca6e0be7aa78c23adda1da48f6967ad4cfe7ebee (patch)
tree8cddd87a0a66291dfe111163e0d775a36a7ea929
parentd41dee1b4366dc685eaa2c435b01be03aef9929b (diff)
downloadpaludis-ca6e0be7aa78c23adda1da48f6967ad4cfe7ebee.tar.gz
paludis-ca6e0be7aa78c23adda1da48f6967ad4cfe7ebee.tar.xz
More metadata
-rw-r--r--paludis/repositories/gemcutter/Makefile.am4
-rw-r--r--paludis/repositories/gemcutter/gemcutter_dependencies_key.cc305
-rw-r--r--paludis/repositories/gemcutter/gemcutter_dependencies_key.hh77
-rw-r--r--paludis/repositories/gemcutter/gemcutter_id.cc171
-rw-r--r--paludis/repositories/gemcutter/gemcutter_repository_store.cc2
-rw-r--r--paludis/repositories/gemcutter/gemcutter_uri_key.cc160
-rw-r--r--paludis/repositories/gemcutter/gemcutter_uri_key.hh71
-rw-r--r--paludis/repositories/gemcutter/json_common-fwd.hh3
-rw-r--r--paludis/repositories/gemcutter/json_common.hh39
-rw-r--r--paludis/repositories/gemcutter/json_things.cc170
10 files changed, 991 insertions, 11 deletions
diff --git a/paludis/repositories/gemcutter/Makefile.am b/paludis/repositories/gemcutter/Makefile.am
index 5c2fe6e..eb501fe 100644
--- a/paludis/repositories/gemcutter/Makefile.am
+++ b/paludis/repositories/gemcutter/Makefile.am
@@ -12,14 +12,18 @@ DEFS= \
noinst_LTLIBRARIES = libpaludisgemcutterrepository.la
noinst_HEADERS = \
+ gemcutter_dependencies_key.hh \
gemcutter_id.hh gemcutter_id-fwd.hh \
gemcutter_repository.hh gemcutter_repository-fwd.hh \
gemcutter_repository_store.hh \
+ gemcutter_uri_key.hh \
json_common.hh json_common-fwd.hh \
json_things_handle.hh json_things_handle-fwd.hh
libpaludisgemcutterrepository_la_SOURCES = \
+ gemcutter_dependencies_key.cc \
gemcutter_id.cc \
+ gemcutter_uri_key.cc \
gemcutter_repository.cc \
gemcutter_repository_store.cc \
json_common.cc \
diff --git a/paludis/repositories/gemcutter/gemcutter_dependencies_key.cc b/paludis/repositories/gemcutter/gemcutter_dependencies_key.cc
new file mode 100644
index 0000000..078bb73
--- /dev/null
+++ b/paludis/repositories/gemcutter/gemcutter_dependencies_key.cc
@@ -0,0 +1,305 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/gemcutter/gemcutter_dependencies_key.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/pimp-impl.hh>
+#include <paludis/util/singleton-impl.hh>
+#include <paludis/util/return_literal_function.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/make_shared_copy.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/spec_tree.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/partially_made_package_dep_spec.hh>
+#include <paludis/environment.hh>
+#include <paludis/selection.hh>
+#include <paludis/generator.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/version_requirements.hh>
+#include <paludis/version_operator.hh>
+#include <paludis/version_spec.hh>
+#include <sstream>
+#include <algorithm>
+#include <vector>
+
+using namespace paludis;
+using namespace paludis::gemcutter_repository;
+
+GemcutterDependenciesError::GemcutterDependenciesError(const std::string & s) throw () :
+ Exception(s)
+{
+}
+
+namespace
+{
+ struct Printer
+ {
+ std::stringstream s;
+ const Environment * const env;
+ DependencySpecTree::ItemFormatter formatter;
+ const unsigned indent;
+ const bool flat;
+ bool need_space;
+
+ Printer(
+ const Environment * const e,
+ const DependencySpecTree::ItemFormatter & f,
+ const bool b) :
+ env(e),
+ formatter(f),
+ indent(0),
+ flat(b),
+ need_space(false)
+ {
+ }
+
+ void visit(const DependencySpecTree::NodeType<PackageDepSpec>::Type & node)
+ {
+ if (! flat)
+ s << formatter.indent(indent + 1);
+ else if (need_space)
+ s << " ";
+ else
+ need_space = true;
+
+ if (env)
+ {
+ if (! (*env)[selection::SomeArbitraryVersion(generator::Matches(*node.spec(), { }) |
+ filter::InstalledAtRoot(env->preferred_root_key()->value()))]->empty())
+ s << formatter.format(*node.spec(), format::Installed());
+ else if (! (*env)[selection::SomeArbitraryVersion(generator::Matches(*node.spec(), { }) |
+ filter::SupportsAction<InstallAction>() | filter::NotMasked())]->empty())
+ s << formatter.format(*node.spec(), format::Installable());
+ else
+ s << formatter.format(*node.spec(), format::Plain());
+ }
+ else
+ s << formatter.format(*node.spec(), format::Plain());
+
+ if (! flat)
+ s << formatter.newline();
+ }
+
+ void visit(const DependencySpecTree::NodeType<BlockDepSpec>::Type &)
+ {
+ }
+
+ void visit(const DependencySpecTree::NodeType<DependenciesLabelsDepSpec>::Type & node)
+ {
+ if (! flat)
+ s << formatter.indent(indent);
+ else if (need_space)
+ s << " ";
+ else
+ need_space = true;
+
+ s << formatter.format(*node.spec(), format::Plain());
+
+ if (! flat)
+ s << formatter.newline();
+ }
+
+ void visit(const DependencySpecTree::NodeType<NamedSetDepSpec>::Type &)
+ {
+ }
+
+ void visit(const DependencySpecTree::NodeType<AllDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+
+ void visit(const DependencySpecTree::NodeType<ConditionalDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+
+ void visit(const DependencySpecTree::NodeType<AnyDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+ };
+
+ struct GemcutterDependenciesKeyData :
+ Singleton<GemcutterDependenciesKeyData>
+ {
+ std::shared_ptr<DependenciesLabelsDepSpec> development_dependencies_label;
+ std::shared_ptr<DependenciesLabelsDepSpec> runtime_dependencies_label;
+ std::shared_ptr<DependenciesLabelSequence> initial_labels;
+
+ GemcutterDependenciesKeyData() :
+ development_dependencies_label(std::make_shared<DependenciesLabelsDepSpec>()),
+ runtime_dependencies_label(std::make_shared<DependenciesLabelsDepSpec>()),
+ initial_labels(std::make_shared<DependenciesLabelSequence>())
+ {
+ development_dependencies_label->add_label(std::make_shared<DependenciesBuildLabel>("development", return_literal_function(true)));
+ runtime_dependencies_label->add_label(std::make_shared<DependenciesRunLabel>("runtime", return_literal_function(true)));
+ initial_labels->push_back(*development_dependencies_label->begin());
+ }
+ };
+
+ std::shared_ptr<PackageDepSpec> spec_from(const GemJSONDependency & dep)
+ {
+ std::vector<std::string> tokens;
+ tokenise_whitespace(dep.requirements(), std::back_inserter(tokens));
+
+ if (tokens.size() != 2)
+ throw GemcutterDependenciesError("Couldn't parse requirement '" + stringify(dep.requirements()) + "'");
+
+ VersionOperator op(vo_equal);
+ if (tokens[0] == "<")
+ op = vo_less;
+ else if (tokens[0] == "<=")
+ op = vo_less_equal;
+ else if (tokens[0] == "=")
+ op = vo_equal;
+ else if (tokens[0] == ">")
+ op = vo_greater;
+ else if (tokens[0] == ">=")
+ op = vo_greater_equal;
+ else if (tokens[0] == "~>")
+ op = vo_tilde_greater;
+ else
+ throw GemcutterDependenciesError("Couldn't parse operator in requirement '" + stringify(dep.requirements()) + "'");
+
+ VersionSpec ver(tokens[1], { });
+
+ return make_shared_copy(PackageDepSpec(make_package_dep_spec({ pmpdso_always_use_ranged_deps })
+ .package(QualifiedPackageName("gem/" + dep.name()))
+ .version_requirement(make_named_values<VersionRequirement>(
+ n::version_operator() = op,
+ n::version_spec() = ver
+ ))
+ ));
+ }
+
+ std::shared_ptr<DependencySpecTree> build(
+ const std::shared_ptr<const GemJSONDependencies> & dd,
+ const std::shared_ptr<const GemJSONDependencies> & dr)
+ {
+ auto result(std::make_shared<DependencySpecTree>(std::make_shared<AllDepSpec>()));
+
+ if (dd)
+ {
+ result->top()->append(GemcutterDependenciesKeyData::get_instance()->development_dependencies_label);
+ for (auto i(dd->dependencies().begin()), i_end(dd->dependencies().end()) ;
+ i != i_end ; ++i)
+ result->top()->append(spec_from(*i));
+ }
+
+ if (dr)
+ {
+ result->top()->append(GemcutterDependenciesKeyData::get_instance()->runtime_dependencies_label);
+ for (auto i(dr->dependencies().begin()), i_end(dr->dependencies().end()) ;
+ i != i_end ; ++i)
+ result->top()->append(spec_from(*i));
+ }
+
+ return result;
+ }
+}
+
+namespace paludis
+{
+ template <>
+ struct Imp<GemcutterDependenciesKey>
+ {
+ const Environment * const env;
+ const std::string * const raw_name;
+ const std::string * const human_name;
+ const MetadataKeyType type;
+ const std::shared_ptr<DependencySpecTree> value;
+
+ Imp(
+ const Environment * const e,
+ const std::string * const r,
+ const std::string * const h,
+ const MetadataKeyType t,
+ const std::shared_ptr<const GemJSONDependencies> & dd,
+ const std::shared_ptr<const GemJSONDependencies> & dr) :
+ env(e),
+ raw_name(r),
+ human_name(h),
+ type(t),
+ value(build(dd, dr))
+ {
+ }
+ };
+}
+
+GemcutterDependenciesKey::GemcutterDependenciesKey(const Environment * const e, const std::string * const r, const std::string * const h,
+ const MetadataKeyType t, const std::shared_ptr<const GemJSONDependencies> & dd, const std::shared_ptr<const GemJSONDependencies> & dr) :
+ Pimp<GemcutterDependenciesKey>(e, r, h, t, dd, dr),
+ _imp(Pimp<GemcutterDependenciesKey>::_imp)
+{
+}
+
+GemcutterDependenciesKey::~GemcutterDependenciesKey() = default;
+
+const std::shared_ptr<const DependencySpecTree>
+GemcutterDependenciesKey::value() const
+{
+ return _imp->value;
+}
+
+const std::string
+GemcutterDependenciesKey::raw_name() const
+{
+ return *_imp->raw_name;
+}
+
+const std::string
+GemcutterDependenciesKey::human_name() const
+{
+ return *_imp->human_name;
+}
+
+MetadataKeyType
+GemcutterDependenciesKey::type() const
+{
+ return _imp->type;
+}
+
+const std::shared_ptr<const DependenciesLabelSequence>
+GemcutterDependenciesKey::initial_labels() const
+{
+ return GemcutterDependenciesKeyData::get_instance()->initial_labels;
+}
+
+std::string
+GemcutterDependenciesKey::pretty_print(const DependencySpecTree::ItemFormatter & f) const
+{
+ Printer p{_imp->env, f, false};
+ _imp->value->top()->accept(p);
+ return p.s.str();
+}
+
+std::string
+GemcutterDependenciesKey::pretty_print_flat(const DependencySpecTree::ItemFormatter & f) const
+{
+ Printer p{_imp->env, f, true};
+ _imp->value->top()->accept(p);
+ return p.s.str();
+}
+
+template class Pimp<GemcutterDependenciesKey>;
+
diff --git a/paludis/repositories/gemcutter/gemcutter_dependencies_key.hh b/paludis/repositories/gemcutter/gemcutter_dependencies_key.hh
new file mode 100644
index 0000000..b1e973e
--- /dev/null
+++ b/paludis/repositories/gemcutter/gemcutter_dependencies_key.hh
@@ -0,0 +1,77 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_GEMCUTTER_GEMCUTTER_DEPENDENCIES_KEY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMCUTTER_GEMCUTTER_DEPENDENCIES_KEY_HH 1
+
+#include <paludis/repositories/gemcutter/json_common.hh>
+#include <paludis/util/pimp.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/environment-fwd.hh>
+
+namespace paludis
+{
+ namespace gemcutter_repository
+ {
+ class PALUDIS_VISIBLE GemcutterDependenciesError :
+ public Exception
+ {
+ public:
+ GemcutterDependenciesError(const std::string &) throw ();
+ };
+
+ class GemcutterDependenciesKey :
+ public MetadataSpecTreeKey<DependencySpecTree>,
+ private Pimp<GemcutterDependenciesKey>
+ {
+ private:
+ Pimp<GemcutterDependenciesKey>::ImpPtr & _imp;
+
+ public:
+ GemcutterDependenciesKey(
+ const Environment * const e,
+ const std::string * const,
+ const std::string * const,
+ const MetadataKeyType,
+ const std::shared_ptr<const GemJSONDependencies> &,
+ const std::shared_ptr<const GemJSONDependencies> &);
+
+ ~GemcutterDependenciesKey();
+
+ ///\}
+
+ virtual const std::shared_ptr<const DependencySpecTree> value() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::string raw_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string human_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual MetadataKeyType type() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::shared_ptr<const DependenciesLabelSequence> initial_labels() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gemcutter/gemcutter_id.cc b/paludis/repositories/gemcutter/gemcutter_id.cc
index 613e42a..85a7bd6 100644
--- a/paludis/repositories/gemcutter/gemcutter_id.cc
+++ b/paludis/repositories/gemcutter/gemcutter_id.cc
@@ -19,6 +19,8 @@
#include <paludis/repositories/gemcutter/gemcutter_id.hh>
#include <paludis/repositories/gemcutter/gemcutter_repository.hh>
+#include <paludis/repositories/gemcutter/gemcutter_uri_key.hh>
+#include <paludis/repositories/gemcutter/gemcutter_dependencies_key.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/simple_visitor_cast.hh>
@@ -32,12 +34,89 @@
#include <paludis/metadata_key.hh>
#include <paludis/literal_metadata_key.hh>
#include <paludis/action.hh>
-#include <paludis/unchoices_key.hh>
#include <paludis/user_dep_spec.hh>
using namespace paludis;
using namespace paludis::gemcutter_repository;
+namespace
+{
+ std::shared_ptr<LiteralMetadataValueKey<std::string> > make_string_key(
+ const std::string & r, const std::string & h, const MetadataKeyType t, const std::string & v)
+ {
+ if (v.empty())
+ return make_null_shared_ptr();
+ else
+ return std::make_shared<LiteralMetadataValueKey<std::string> >(r, h, t, v);
+ }
+
+ std::shared_ptr<GemcutterURIKey> make_uri(
+ const std::string * const r, const std::string * const h, const MetadataKeyType t, const std::string & v)
+ {
+ if (v.empty())
+ return make_null_shared_ptr();
+ else
+ return std::make_shared<GemcutterURIKey>(r, h, t, v);
+ }
+
+ std::shared_ptr<GemcutterDependenciesKey> make_dependencies(
+ const Environment * const e,
+ const std::string * const r, const std::string * const h, const MetadataKeyType t,
+ const std::shared_ptr<const GemJSONDependencies> & dd,
+ const std::shared_ptr<const GemJSONDependencies> & dr)
+ {
+ return std::make_shared<GemcutterDependenciesKey>(e, r, h, t, dd, dr);
+ }
+
+ struct GemcutterIDStrings :
+ Singleton<GemcutterIDStrings>
+ {
+ const std::string bug_tracker_uri_raw;
+ const std::string bug_tracker_uri_human;
+
+ const std::string gem_uri_raw;
+ const std::string gem_uri_human;
+
+ const std::string homepage_uri_raw;
+ const std::string homepage_uri_human;
+
+ const std::string mailing_list_uri_raw;
+ const std::string mailing_list_uri_human;
+
+ const std::string project_uri_raw;
+ const std::string project_uri_human;
+
+ const std::string source_code_uri_raw;
+ const std::string source_code_uri_human;
+
+ const std::string wiki_uri_raw;
+ const std::string wiki_uri_human;
+
+ const std::string dependencies_raw;
+ const std::string dependencies_human;
+
+ GemcutterIDStrings() :
+ bug_tracker_uri_raw("bug_tracker_uri"),
+ bug_tracker_uri_human("Bug tracker URI"),
+ gem_uri_raw("gem_uri"),
+ gem_uri_human("Gem URI"),
+ homepage_uri_raw("homepage_uri"),
+ homepage_uri_human("Homepage"),
+ mailing_list_uri_raw("mailing_list_uri"),
+ mailing_list_uri_human("Mailing list URI"),
+ project_uri_raw("project_uri"),
+ project_uri_human("Project URI"),
+ source_code_uri_raw("source_code_uri"),
+ source_code_uri_human("Sourcecode URI"),
+ wiki_uri_raw("wiki_uri"),
+ wiki_uri_human("Wiki URI"),
+ dependencies_raw("dependencies"),
+ dependencies_human("Dependencies")
+ {
+ }
+ };
+}
+
namespace paludis
{
template <>
@@ -48,11 +127,69 @@ namespace paludis
const VersionSpec version;
const GemcutterRepository * const repo;
+ std::shared_ptr<LiteralMetadataValueKey<SlotName> > slot_key;
+ std::shared_ptr<LiteralMetadataValueKey<std::string> > authors_key;
+ std::shared_ptr<LiteralMetadataValueKey<std::string> > info_key;
+ std::shared_ptr<GemcutterURIKey> bug_tracker_uri_key;
+ std::shared_ptr<GemcutterURIKey> gem_uri_key;
+ std::shared_ptr<GemcutterURIKey> homepage_uri_key;
+ std::shared_ptr<GemcutterURIKey> mailing_list_uri_key;
+ std::shared_ptr<GemcutterURIKey> project_uri_key;
+ std::shared_ptr<GemcutterURIKey> source_code_uri_key;
+ std::shared_ptr<GemcutterURIKey> wiki_uri_key;
+ std::shared_ptr<GemcutterDependenciesKey> dependencies_key;
+
Imp(const GemcutterIDParams & e) :
env(e.environment()),
name(CategoryNamePart("gem"), PackageNamePart(e.info().name())),
version(e.info().version(), { }),
- repo(e.repository())
+ repo(e.repository()),
+ slot_key(std::make_shared<LiteralMetadataValueKey<SlotName> >("slot", "Slot", mkt_internal, SlotName(e.info().version()))),
+ authors_key(make_string_key("authors", "Authors", mkt_author, e.info().authors())),
+ info_key(make_string_key("info", "Info", mkt_significant, e.info().info())),
+ bug_tracker_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->bug_tracker_uri_raw,
+ &GemcutterIDStrings::get_instance()->bug_tracker_uri_human,
+ mkt_normal,
+ e.info().bug_tracker_uri())),
+ gem_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->gem_uri_raw,
+ &GemcutterIDStrings::get_instance()->gem_uri_human,
+ mkt_normal,
+ e.info().gem_uri())),
+ homepage_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->homepage_uri_raw,
+ &GemcutterIDStrings::get_instance()->homepage_uri_human,
+ mkt_significant,
+ e.info().homepage_uri())),
+ mailing_list_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->mailing_list_uri_raw,
+ &GemcutterIDStrings::get_instance()->mailing_list_uri_human,
+ mkt_normal,
+ e.info().mailing_list_uri())),
+ project_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->project_uri_raw,
+ &GemcutterIDStrings::get_instance()->project_uri_human,
+ mkt_normal,
+ e.info().project_uri())),
+ source_code_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->source_code_uri_raw,
+ &GemcutterIDStrings::get_instance()->source_code_uri_human,
+ mkt_normal,
+ e.info().source_code_uri())),
+ wiki_uri_key(make_uri(
+ &GemcutterIDStrings::get_instance()->wiki_uri_raw,
+ &GemcutterIDStrings::get_instance()->wiki_uri_human,
+ mkt_normal,
+ e.info().wiki_uri())),
+ dependencies_key(make_dependencies(
+ env,
+ &GemcutterIDStrings::get_instance()->dependencies_raw,
+ &GemcutterIDStrings::get_instance()->dependencies_human,
+ mkt_dependencies,
+ e.info().development_dependencies(),
+ e.info().runtime_dependencies()
+ ))
{
}
};
@@ -62,6 +199,28 @@ GemcutterID::GemcutterID(const GemcutterIDParams & entry) :
Pimp<GemcutterID>(entry),
_imp(Pimp<GemcutterID>::_imp)
{
+ add_metadata_key(_imp->slot_key);
+
+ if (_imp->authors_key)
+ add_metadata_key(_imp->authors_key);
+ if (_imp->info_key)
+ add_metadata_key(_imp->info_key);
+ if (_imp->bug_tracker_uri_key)
+ add_metadata_key(_imp->bug_tracker_uri_key);
+ if (_imp->gem_uri_key)
+ add_metadata_key(_imp->gem_uri_key);
+ if (_imp->homepage_uri_key)
+ add_metadata_key(_imp->homepage_uri_key);
+ if (_imp->mailing_list_uri_key)
+ add_metadata_key(_imp->mailing_list_uri_key);
+ if (_imp->project_uri_key)
+ add_metadata_key(_imp->project_uri_key);
+ if (_imp->source_code_uri_key)
+ add_metadata_key(_imp->source_code_uri_key);
+ if (_imp->wiki_uri_key)
+ add_metadata_key(_imp->wiki_uri_key);
+ if (_imp->dependencies_key)
+ add_metadata_key(_imp->dependencies_key);
}
GemcutterID::~GemcutterID()
@@ -204,7 +363,7 @@ GemcutterID::provide_key() const
const std::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
GemcutterID::dependencies_key() const
{
- return std::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >();
+ return _imp->dependencies_key;
}
const std::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
@@ -234,7 +393,7 @@ GemcutterID::suggested_dependencies_key() const
const std::shared_ptr<const MetadataValueKey<std::string> >
GemcutterID::short_description_key() const
{
- return make_null_shared_ptr();
+ return _imp->info_key;
}
const std::shared_ptr<const MetadataValueKey<std::string> >
@@ -252,7 +411,7 @@ GemcutterID::fetches_key() const
const std::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >
GemcutterID::homepage_key() const
{
- return std::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >();
+ return _imp->homepage_uri_key;
}
const std::shared_ptr<const MetadataValueKey<std::shared_ptr<const Contents> > >
@@ -282,7 +441,7 @@ GemcutterID::choices_key() const
const std::shared_ptr<const MetadataValueKey<SlotName> >
GemcutterID::slot_key() const
{
- return make_null_shared_ptr();
+ return _imp->slot_key;
}
template class Pimp<GemcutterID>;
diff --git a/paludis/repositories/gemcutter/gemcutter_repository_store.cc b/paludis/repositories/gemcutter/gemcutter_repository_store.cc
index 4a54282..7ee0861 100644
--- a/paludis/repositories/gemcutter/gemcutter_repository_store.cc
+++ b/paludis/repositories/gemcutter/gemcutter_repository_store.cc
@@ -110,7 +110,7 @@ GemcutterRepositoryStore::_populate()
{
Log::get_instance()->message("gemcutter_repository.not_available", ll_warning, lc_context)
<< "Not loading '" << all_gems << "' for ::" << stringify(_imp->repo->name()) << " due to "
- << "exception '" << e.message() << "' (" << e.what() << ")";
+ << "exception '" << e.backtrace(": ") << ": " << e.message() << "' (" << e.what() << ")";
_imp->categories->clear();
_imp->package_names.clear();
diff --git a/paludis/repositories/gemcutter/gemcutter_uri_key.cc b/paludis/repositories/gemcutter/gemcutter_uri_key.cc
new file mode 100644
index 0000000..c17ee50
--- /dev/null
+++ b/paludis/repositories/gemcutter/gemcutter_uri_key.cc
@@ -0,0 +1,160 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/gemcutter/gemcutter_uri_key.hh>
+#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/pimp-impl.hh>
+#include <paludis/spec_tree.hh>
+#include <paludis/dep_spec.hh>
+#include <sstream>
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::gemcutter_repository;
+
+namespace
+{
+ std::shared_ptr<SimpleURISpecTree> parse(const std::string & s)
+ {
+ auto result(std::make_shared<SimpleURISpecTree>(std::make_shared<AllDepSpec>()));
+ result->top()->append(std::make_shared<SimpleURIDepSpec>(s));
+ return result;
+ }
+
+ struct Printer
+ {
+ const bool flat;
+ const SimpleURISpecTree::ItemFormatter & formatter;
+ int indent;
+ bool need_space;
+ std::stringstream s;
+
+ Printer(const bool f, const SimpleURISpecTree::ItemFormatter & i) :
+ flat(f),
+ formatter(i),
+ indent(0),
+ need_space(false)
+ {
+ }
+
+ void visit(const SimpleURISpecTree::NodeType<SimpleURIDepSpec>::Type & node)
+ {
+ if (! flat)
+ s << formatter.indent(indent);
+ else if (need_space)
+ s << " ";
+ else
+ need_space = true;
+
+ s << formatter.format(*node.spec(), format::Plain());
+
+ if (! flat)
+ s << formatter.newline();
+ }
+
+ void visit(const SimpleURISpecTree::NodeType<AllDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+
+ void visit(const SimpleURISpecTree::NodeType<ConditionalDepSpec>::Type & node)
+ {
+ std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
+ }
+ };
+}
+
+namespace paludis
+{
+ template <>
+ struct Imp<GemcutterURIKey>
+ {
+ const std::string * const raw_name;
+ const std::string * const human_name;
+ const MetadataKeyType type;
+ const std::string value_string;
+ const std::shared_ptr<SimpleURISpecTree> value;
+
+ Imp(
+ const std::string * const r,
+ const std::string * const h,
+ const MetadataKeyType t,
+ const std::string & v) :
+ raw_name(r),
+ human_name(h),
+ type(t),
+ value_string(v),
+ value(parse(v))
+ {
+ }
+ };
+}
+
+GemcutterURIKey::GemcutterURIKey(const std::string * const r, const std::string * const h,
+ const MetadataKeyType t, const std::string & v) :
+ Pimp<GemcutterURIKey>(r, h, t, v),
+ _imp(Pimp<GemcutterURIKey>::_imp)
+{
+}
+
+GemcutterURIKey::~GemcutterURIKey() = default;
+
+const std::shared_ptr<const SimpleURISpecTree>
+GemcutterURIKey::value() const
+{
+ return _imp->value;
+}
+
+const std::string
+GemcutterURIKey::raw_name() const
+{
+ return *_imp->raw_name;
+}
+
+const std::string
+GemcutterURIKey::human_name() const
+{
+ return *_imp->human_name;
+}
+
+MetadataKeyType
+GemcutterURIKey::type() const
+{
+ return _imp->type;
+}
+
+std::string
+GemcutterURIKey::pretty_print(const SimpleURISpecTree::ItemFormatter & f) const
+{
+ Printer p{false, f};
+ _imp->value->top()->accept(p);
+ return p.s.str();
+}
+
+std::string
+GemcutterURIKey::pretty_print_flat(const SimpleURISpecTree::ItemFormatter & f) const
+{
+ Printer p{true, f};
+ _imp->value->top()->accept(p);
+ return p.s.str();
+}
+
+template class Pimp<GemcutterURIKey>;
+
diff --git a/paludis/repositories/gemcutter/gemcutter_uri_key.hh b/paludis/repositories/gemcutter/gemcutter_uri_key.hh
new file mode 100644
index 0000000..7d4a555
--- /dev/null
+++ b/paludis/repositories/gemcutter/gemcutter_uri_key.hh
@@ -0,0 +1,71 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_GEMCUTTER_GEMCUTTER_URI_KEY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GEMCUTTER_GEMCUTTER_URI_KEY_HH 1
+
+#include <paludis/metadata_key.hh>
+#include <paludis/util/pimp.hh>
+
+namespace paludis
+{
+ namespace gemcutter_repository
+ {
+ class GemcutterURIKey :
+ public MetadataSpecTreeKey<SimpleURISpecTree>,
+ private Pimp<GemcutterURIKey>
+ {
+ private:
+ Pimp<GemcutterURIKey>::ImpPtr & _imp;
+
+ public:
+ GemcutterURIKey(
+ const std::string * const,
+ const std::string * const,
+ const MetadataKeyType,
+ const std::string &);
+
+ ~GemcutterURIKey();
+
+ ///\}
+
+ virtual const std::shared_ptr<const SimpleURISpecTree> value() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::string raw_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string human_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual MetadataKeyType type() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return a multiline-line indented and formatted version of our
+ * value, using the supplied Formatter to format individual items.
+ */
+ virtual std::string pretty_print(const SimpleURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return a single-line formatted version of our value, using the
+ * supplied Formatter to format individual items.
+ */
+ virtual std::string pretty_print_flat(const SimpleURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/gemcutter/json_common-fwd.hh b/paludis/repositories/gemcutter/json_common-fwd.hh
index ab2ae04..545eb5f 100644
--- a/paludis/repositories/gemcutter/json_common-fwd.hh
+++ b/paludis/repositories/gemcutter/json_common-fwd.hh
@@ -27,7 +27,10 @@ namespace paludis
namespace gemcutter_repository
{
class JSONError;
+
class GemJSONInfo;
+ class GemJSONDependency;
+ class GemJSONDependencies;
typedef std::function<void (const GemJSONInfo &)> ParsedOneGemCallback;
}
diff --git a/paludis/repositories/gemcutter/json_common.hh b/paludis/repositories/gemcutter/json_common.hh
index 196a4e0..9cf45e7 100644
--- a/paludis/repositories/gemcutter/json_common.hh
+++ b/paludis/repositories/gemcutter/json_common.hh
@@ -23,21 +23,60 @@
#include <paludis/repositories/gemcutter/json_common-fwd.hh>
#include <paludis/util/exception.hh>
#include <paludis/util/named_value.hh>
+#include <list>
+#include <memory>
namespace paludis
{
namespace n
{
+ typedef Name<struct authors_name> authors;
+ typedef Name<struct bug_tracker_uri_name> bug_tracker_uri;
+ typedef Name<struct dependencies_name> dependencies;
+ typedef Name<struct development_dependencies_name> development_dependencies;
+ typedef Name<struct documentation_uri_name> documentation_uri;
+ typedef Name<struct gem_uri_name> gem_uri;
+ typedef Name<struct homepage_uri_name> homepage_uri;
+ typedef Name<struct info_name> info;
+ typedef Name<struct mailing_list_uri_name> mailing_list_uri;
typedef Name<struct name_name> name;
+ typedef Name<struct project_uri_name> project_uri;
+ typedef Name<struct requirements_name> requirements;
+ typedef Name<struct runtime_dependencies_name> runtime_dependencies;
+ typedef Name<struct source_code_uri_name> source_code_uri;
typedef Name<struct version_name> version;
+ typedef Name<struct wiki_uri_name> wiki_uri;
}
namespace gemcutter_repository
{
+ struct GemJSONDependency
+ {
+ NamedValue<n::name, std::string> name;
+ NamedValue<n::requirements, std::string> requirements;
+ };
+
+ struct GemJSONDependencies
+ {
+ NamedValue<n::dependencies, std::list<GemJSONDependency> > dependencies;
+ };
+
struct GemJSONInfo
{
+ NamedValue<n::authors, std::string> authors;
+ NamedValue<n::bug_tracker_uri, std::string> bug_tracker_uri;
+ NamedValue<n::development_dependencies, std::shared_ptr<GemJSONDependencies> > development_dependencies;
+ NamedValue<n::documentation_uri, std::string> documentation_uri;
+ NamedValue<n::gem_uri, std::string> gem_uri;
+ NamedValue<n::homepage_uri, std::string> homepage_uri;
+ NamedValue<n::info, std::string> info;
+ NamedValue<n::mailing_list_uri, std::string> mailing_list_uri;
NamedValue<n::name, std::string> name;
+ NamedValue<n::project_uri, std::string> project_uri;
+ NamedValue<n::runtime_dependencies, std::shared_ptr<GemJSONDependencies> > runtime_dependencies;
+ NamedValue<n::source_code_uri, std::string> source_code_uri;
NamedValue<n::version, std::string> version;
+ NamedValue<n::wiki_uri, std::string> wiki_uri;
};
class PALUDIS_VISIBLE JSONError :
diff --git a/paludis/repositories/gemcutter/json_things.cc b/paludis/repositories/gemcutter/json_things.cc
index b525dab..e7c1d0d 100644
--- a/paludis/repositories/gemcutter/json_things.cc
+++ b/paludis/repositories/gemcutter/json_things.cc
@@ -28,12 +28,50 @@
using namespace paludis;
using namespace paludis::gemcutter_repository;
+namespace
+{
+ std::shared_ptr<GemJSONDependencies> parse_deps(json_t * dependencies_id)
+ {
+ std::shared_ptr<GemJSONDependencies> dependencies(std::make_shared<GemJSONDependencies>(
+ make_named_values<GemJSONDependencies>(
+ n::dependencies() = std::list<GemJSONDependency>()
+ )));
+ for (int n(0), n_end(json_array_size(dependencies_id)) ; n != n_end ; ++n)
+ {
+ json_t * dep(json_array_get(dependencies_id, n));
+ if ((! dep) || (! json_is_object(dep)))
+ throw JSONError("Entry dep is not an object");
+
+ std::string dep_name, dep_requirements;
+
+ json_t * dep_name_id(json_object_get(dep, "name"));
+ if ((! dep_name_id) || json_is_null(dep_name_id) || ! json_is_string(dep_name_id))
+ throw JSONError("Entry dep name is not a string");
+ dep_name = std::string(json_string_value(dep_name_id));
+
+ json_t * dep_requirements_id(json_object_get(dep, "requirements"));
+ if ((! dep_requirements_id) || json_is_null(dep_requirements_id) || ! json_is_string(dep_requirements_id))
+ throw JSONError("Entry dep requirements is not a string");
+ dep_requirements = std::string(json_string_value(dep_requirements_id));
+
+ dependencies->dependencies().push_back(make_named_values<GemJSONDependency>(
+ n::name() = dep_name,
+ n::requirements() = dep_requirements
+ ));
+ }
+
+ return dependencies;
+ }
+}
+
extern "C"
void
gemcutter_json_things_parse_all_gems(
const FSPath & path,
const ParsedOneGemCallback & parsed_one_gem)
{
+ Context context("When parsing '" + stringify(path) + "':");
+
json_error_t error;
json_t * root(json_load_file(stringify(path).c_str(), &error));
@@ -46,7 +84,12 @@ gemcutter_json_things_parse_all_gems(
for (int i(0), i_end(json_array_size(root)) ;
i != i_end ; ++i)
{
- std::string name, version;
+ Context item_context("When parsing entry " + stringify(i) + ":");
+
+ std::string name, version, authors, bug_tracker_uri, documentation_uri, gem_uri, homepage_uri,
+ info, mailing_list_uri, project_uri, source_code_uri, wiki_uri;
+
+ std::shared_ptr<GemJSONDependencies> development_dependencies, runtime_dependencies;
json_t * entry(json_array_get(root, i));
if ((! entry) || (! json_is_object(entry)))
@@ -62,11 +105,130 @@ gemcutter_json_things_parse_all_gems(
throw JSONError("Entry version is not a string");
version = std::string(json_string_value(version_id));
- GemJSONInfo info(make_named_values<GemJSONInfo>(
+ Context better_item_context("When handling metadata for '" + name + "' '" + version + "':");
+
+ json_t * authors_id(json_object_get(entry, "authors"));
+ if (! json_is_null(authors_id))
+ {
+ if ((! authors_id) || (! json_is_string(authors_id)))
+ throw JSONError("Entry authors is not a string");
+ authors = std::string(json_string_value(authors_id));
+ }
+
+ json_t * bug_tracker_uri_id(json_object_get(entry, "bug_tracker_uri"));
+ if (! json_is_null(bug_tracker_uri_id))
+ {
+ if ((! bug_tracker_uri_id) || (! json_is_string(bug_tracker_uri_id)))
+ throw JSONError("Entry bug_tracker_uri is not a string");
+ bug_tracker_uri = std::string(json_string_value(bug_tracker_uri_id));
+ }
+
+ json_t * documentation_uri_id(json_object_get(entry, "documentation_uri"));
+ if (! json_is_null(documentation_uri_id))
+ {
+ if ((! documentation_uri_id) || (! json_is_string(documentation_uri_id)))
+ throw JSONError("Entry documentation_uri is not a string");
+ documentation_uri = std::string(json_string_value(documentation_uri_id));
+ }
+
+ json_t * gem_uri_id(json_object_get(entry, "gem_uri"));
+ if (! json_is_null(gem_uri_id))
+ {
+ if ((! gem_uri_id) || (! json_is_string(gem_uri_id)))
+ throw JSONError("Entry gem_uri is not a string");
+ gem_uri = std::string(json_string_value(gem_uri_id));
+ }
+
+ json_t * homepage_uri_id(json_object_get(entry, "homepage_uri"));
+ if (! json_is_null(homepage_uri_id))
+ {
+ if ((! homepage_uri_id) || (! json_is_string(homepage_uri_id)))
+ throw JSONError("Entry homepage_uri is not a string");
+ homepage_uri = std::string(json_string_value(homepage_uri_id));
+ }
+
+ json_t * info_id(json_object_get(entry, "info"));
+ if (! json_is_null(info_id))
+ {
+ if ((! info_id) || (! json_is_string(info_id)))
+ throw JSONError("Entry info is not a string");
+ info = std::string(json_string_value(info_id));
+ }
+
+ json_t * mailing_list_uri_id(json_object_get(entry, "mailing_list_uri"));
+ if (! json_is_null(mailing_list_uri_id))
+ {
+ if ((! mailing_list_uri_id) || (! json_is_string(mailing_list_uri_id)))
+ throw JSONError("Entry mailing_list_uri is not a string");
+ mailing_list_uri = std::string(json_string_value(mailing_list_uri_id));
+ }
+
+ json_t * project_uri_id(json_object_get(entry, "project_uri"));
+ if (! json_is_null(project_uri_id))
+ {
+ if ((! project_uri_id) || (! json_is_string(project_uri_id)))
+ throw JSONError("Entry project_uri is not a string");
+ project_uri = std::string(json_string_value(project_uri_id));
+ }
+
+ json_t * source_code_uri_id(json_object_get(entry, "source_code_uri"));
+ if (! json_is_null(source_code_uri_id))
+ {
+ if ((! source_code_uri_id) || (! json_is_string(source_code_uri_id)))
+ throw JSONError("Entry source_code_uri is not a string");
+ source_code_uri = std::string(json_string_value(source_code_uri_id));
+ }
+
+ json_t * wiki_uri_id(json_object_get(entry, "wiki_uri"));
+ if (! json_is_null(wiki_uri_id))
+ {
+ if ((! wiki_uri_id) || (! json_is_string(wiki_uri_id)))
+ throw JSONError("Entry wiki_uri is not a string");
+ wiki_uri = std::string(json_string_value(wiki_uri_id));
+ }
+
+ json_t * dependencies_id(json_object_get(entry, "dependencies"));
+ if (! json_is_null(dependencies_id))
+ {
+ if ((! dependencies_id) || (! json_is_object(dependencies_id)))
+ throw JSONError("Entry dependencies is not an object");
+
+ json_t * development_dependencies_id(json_object_get(dependencies_id, "development"));
+ if (! json_is_null(development_dependencies_id))
+ {
+ if ((! development_dependencies_id) || (! json_is_array(development_dependencies_id)))
+ throw JSONError("Entry development dependencies is not an array");
+
+ development_dependencies = parse_deps(development_dependencies_id);
+ }
+
+ json_t * runtime_dependencies_id(json_object_get(dependencies_id, "runtime"));
+ if (! json_is_null(runtime_dependencies_id))
+ {
+ if ((! runtime_dependencies_id) || (! json_is_array(runtime_dependencies_id)))
+ throw JSONError("Entry runtime dependencies is not an array");
+
+ runtime_dependencies = parse_deps(runtime_dependencies_id);
+ }
+ }
+
+ GemJSONInfo json_info(make_named_values<GemJSONInfo>(
+ n::authors() = authors,
+ n::bug_tracker_uri() = bug_tracker_uri,
+ n::development_dependencies() = development_dependencies,
+ n::documentation_uri() = documentation_uri,
+ n::gem_uri() = gem_uri,
+ n::homepage_uri() = homepage_uri,
+ n::info() = info,
+ n::mailing_list_uri() = mailing_list_uri,
n::name() = name,
- n::version() = version
+ n::project_uri() = project_uri,
+ n::runtime_dependencies() = runtime_dependencies,
+ n::source_code_uri() = source_code_uri,
+ n::version() = version,
+ n::wiki_uri() = wiki_uri
));
- parsed_one_gem(info);
+ parsed_one_gem(json_info);
}
json_decref(root);