Exheredludis/ruby/paludis_ruby.cc

407 lines
15 KiB
C++
Raw Normal View History

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
2006-09-23 13:50:45 +02:00
/*
2013-09-08 09:32:58 +02:00
* Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2013 Ciaran McCreesh
* Copyright (c) 2006, 2007, 2008 Richard Brown
2006-09-23 13:50:45 +02:00
*
* 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_ruby.hh>
2007-09-26 02:14:11 +02:00
#include <paludis/util/config_file.hh>
#include <paludis/util/singleton-impl.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/match_package.hh>
#include <paludis/version_spec.hh>
#include <paludis/version_operator.hh>
#include <paludis/about.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/action.hh>
#include <ruby.h>
#include <list>
#include <ctype.h>
using namespace paludis;
using namespace paludis::ruby;
Fix assorted build failures with clang ../../../paludis/paludis/util/sequence-impl.hh:162:21: error: expected expression _imp->list.sort<const C_ &>(c); - just a missing "template" ../../paludis/paludis/util/visitor.hh:322:24: error: no viable overloaded '=' result = _unwrapped_visitor.visit(t); [snip] ../../paludis/paludis/mask.cc:43:17: note: in instantiation of function template specialization 'paludis::DeclareAbstractAcceptMethods<paludis::Mask, paludis::TypeListEntry<paludis::UserMask, paludis::TypeListEntry<paludis::UnacceptedMask, paludis::TypeListEntry<paludis::RepositoryMask, paludis::TypeListEntry<paludis::UnsupportedMask, paludis::TypeListTail> > > > >::make_accept_returning<<lambda at ../../paludis/paludis/mask.cc:44:9>, <lambda at ../../paludis/paludis/mask.cc:45:9>, <lambda at ../../paludis/paludis/mask.cc:46:9>, <lambda at ../../paludis/paludis/mask.cc:47:9> >' requested here return mask.make_accept_returning( /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/basic_string.h:543:7: note: candidate function not viable: 'this' argument has type 'const std::basic_string<char>', but method is not marked const operator=(const basic_string& __str) [snip] - template argument inferred as const and then used for temporary variable that gets assigned, so needs to be forced non-const In file included from ../../../../paludis/paludis/repositories/e/e_choice_value.cc:24: ../../../../paludis/paludis/util/pool-impl.hh:171:23: error: call to function 'operator==' that is neither visible in the template definition nor found by argument-dependent lookup return _value == static_cast<const ConcretePoolKey<T_> &>(other)._value; [snip] ../../../../paludis/paludis/repositories/e/e_choice_value.cc:147:10: note: 'operator==' should be declared prior to the call site or in namespace 'paludis::erepository' bool operator== (const EChoiceValueParams & a, const EChoiceValueParams & b) - see http://clang.llvm.org/compatibility.html#dep_lookup /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/functional:1925:2: error: no matching function for call to object of type 'std::_Bind<std::_Mem_fn<void (paludis::resolver::Decider::*)(const std::shared_ptr<const paludis::resolver::Resolution> &, const std::shared_ptr<const paludis::resolver::Constraint> &, const std::shared_ptr<const paludis::resolver::Decision> &) __attribute__((noreturn)) const> (paludis::resolver::Decider *, std::shared_ptr<paludis::resolver::Resolution>, std::shared_ptr<const paludis::resolver::Constraint>, std::shared_ptr<paludis::resolver::Decision>)>' (*_Base::_M_get_pointer(__functor))( [snip] ../../../paludis/paludis/resolver/decider.cc:936:65: note: in instantiation of function template specialization 'std::function<void ()>::function<std::_Bind<std::_Mem_fn<void (paludis::resolver::Decider::*)(const std::shared_ptr<const paludis::resolver::Resolution> &, const std::shared_ptr<const paludis::resolver::Constraint> &, const std::shared_ptr<const paludis::resolver::Decision> &) __attribute__((noreturn)) const> (paludis::resolver::Decider *, std::shared_ptr<paludis::resolver::Resolution>, std::shared_ptr<const paludis::resolver::Constraint>, std::shared_ptr<paludis::resolver::Decision>)> >' requested here resolution->decision()->accept(WrongDecisionVisitor(std::bind( /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/functional:1211:2: note: candidate template ignored: substitution failure [with _Args = <>]: no matching function for call to object of type 'std::_Mem_fn<void (paludis::resolver::Decider::*)(const std::shared_ptr<const paludis::resolver::Resolution> &, const std::shared_ptr<const paludis::resolver::Constraint> &, const std::shared_ptr<const paludis::resolver::Decision> &) __attribute__((noreturn)) const>' operator()(_Args&&... __args) [snip] - not sure why it doesn't like this, but its nicer with the anonymous function anyway ../../paludis/python/dep_spec.cc:1409:16: error: explicit instantiation of 'paludis::WrappedForwardIterator' must occur in namespace 'paludis' template class WrappedForwardIterator<PythonCompositeDepSpec::ConstIteratorTag, ../../paludis/python/exception.cc:32:16: error: explicit instantiation of 'paludis::Singleton' must occur in namespace 'paludis' template class Singleton<ExceptionRegister>; ../../paludis/ruby/paludis_ruby.cc:38:16: error: explicit instantiation of 'paludis::Singleton' must occur in namespace 'paludis' template class Singleton<RegisterRubyClass>; - self-explanatory
2014-08-28 21:34:37 +02:00
namespace paludis
{
template class Singleton<RegisterRubyClass>;
}
namespace paludis
{
template<>
struct Imp<RegisterRubyClass>
{
std::list<void (*)()> funcs;
};
}
namespace
{
static VALUE c_paludis_module;
static VALUE c_name_error;
static VALUE c_set_name_error;
static VALUE c_category_name_part_error;
static VALUE c_package_name_part_error;
2006-10-27 14:43:53 +02:00
static VALUE c_bad_version_spec_error;
2007-02-22 02:16:22 +01:00
static VALUE c_package_dep_spec_error;
static VALUE c_ambiguous_package_name_error;
static VALUE c_no_such_package_error;
static VALUE c_no_such_repository_error;
2006-11-30 16:01:23 +01:00
static VALUE c_configuration_error;
static VALUE c_config_file_error;
static VALUE c_action_failed_error;
static VALUE c_action_aborted_error;
static VALUE c_bad_version_operator_error;
static VALUE c_got_a_set_not_a_package_dep_spec;
2006-11-30 16:01:23 +01:00
/*
* Document-method: match_package
*
* call-seq:
2011-01-06 14:21:13 +01:00
* match_package(environment, package_dep_spec, package_id, from_package_id, options) -> true or false
*
2007-11-18 16:58:20 +01:00
* Return whether the specified PackageID matches the specified PackageDepSpec.
*
*/
2011-01-06 14:21:13 +01:00
VALUE paludis_match_package(VALUE, VALUE en, VALUE a, VALUE t, VALUE f, VALUE o)
{
try
{
2010-07-22 11:11:47 +02:00
std::shared_ptr<Environment> env = value_to_environment(en);
std::shared_ptr<const PackageDepSpec> spec = value_to_package_dep_spec(a);
std::shared_ptr<const PackageID> target = value_to_package_id(t);
2011-01-06 14:21:13 +01:00
std::shared_ptr<const PackageID> from_package_id = value_to_package_id(f, true);
MatchPackageOptions options(value_to_match_package_options(o));
2011-01-06 14:21:13 +01:00
return match_package(*env, *spec, target, from_package_id, options) ? Qtrue : Qfalse;
}
catch (const std::exception & e)
{
exception_to_ruby_exception(e);
}
}
2007-07-01 02:08:46 +02:00
/*
* Document-method: match_package_in_set
*
* call-seq:
* match_package_in_set(environment, set_spec_tree, package_id, options) -> true or false
*
* Return whether the specified PackageID matches the specified set.
*
*/
VALUE paludis_match_package_in_set(VALUE, VALUE en, VALUE a, VALUE t, VALUE o)
{
try
{
2010-07-22 11:11:47 +02:00
std::shared_ptr<Environment> env = value_to_environment(en);
std::shared_ptr<const SetSpecTree> spec = value_to_dep_tree<SetSpecTree>(a);
std::shared_ptr<const PackageID> target = value_to_package_id(t);
MatchPackageOptions options(value_to_match_package_options(o));
2010-12-28 00:54:51 +01:00
return match_package_in_set(*env, *spec, target, options) ? Qtrue : Qfalse;
}
catch (const std::exception & e)
{
exception_to_ruby_exception(e);
}
}
/*
* Document-method: version_spec_comparator
*
* call-seq:
* version_spec_comparator(operator, left_version_spec, right_version_spec) -> true of false
*
* Applies operator to left_version_spec and right_version_spec
*/
VALUE paludis_version_spec_comparator(VALUE, VALUE op, VALUE left, VALUE right)
{
try
{
const VersionOperator vo = VersionOperator(StringValuePtr(op));
const VersionSpec l = value_to_version_spec(left);
const VersionSpec r = value_to_version_spec(right);
if (vo.as_version_spec_comparator()(l, r))
return true;
return false;
}
catch (const std::exception & e)
{
exception_to_ruby_exception(e);
}
}
}
RegisterRubyClass::RegisterRubyClass() :
_imp()
{
}
RegisterRubyClass::~RegisterRubyClass()
{
}
void
RegisterRubyClass::execute() const
{
for (std::list<void (*)()>::const_iterator f(_imp->funcs.begin()), f_end(_imp->funcs.end()) ;
f != f_end ; ++f)
(*f)();
}
RegisterRubyClass::Register::Register(void (* f)())
{
RegisterRubyClass::get_instance()->_imp->funcs.push_back(f);
}
void paludis::ruby::exception_to_ruby_exception(const std::exception & ee)
{
if (0 != dynamic_cast<const paludis::InternalError *>(&ee))
rb_raise(rb_eRuntimeError, "Unexpected paludis::InternalError: %s (%s)",
dynamic_cast<const paludis::InternalError *>(&ee)->message().c_str(), ee.what());
else if (0 != dynamic_cast<const paludis::GotASetNotAPackageDepSpec *>(&ee))
rb_raise(c_got_a_set_not_a_package_dep_spec, "%s", dynamic_cast<const paludis::GotASetNotAPackageDepSpec *>(&ee)->message().c_str());
2006-10-27 14:43:53 +02:00
else if (0 != dynamic_cast<const paludis::BadVersionSpecError *>(&ee))
rb_raise(c_bad_version_spec_error, "%s", dynamic_cast<const paludis::BadVersionSpecError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::SetNameError *>(&ee))
rb_raise(c_set_name_error, "%s", dynamic_cast<const paludis::SetNameError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::PackageNamePartError *>(&ee))
rb_raise(c_package_name_part_error, "%s", dynamic_cast<const paludis::PackageNamePartError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::CategoryNamePartError *>(&ee))
rb_raise(c_category_name_part_error, "%s", dynamic_cast<const paludis::CategoryNamePartError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::NameError *>(&ee))
rb_raise(c_name_error, "%s", dynamic_cast<const paludis::NameError *>(&ee)->message().c_str());
2007-02-22 02:16:22 +01:00
else if (0 != dynamic_cast<const paludis::PackageDepSpecError *>(&ee))
rb_raise(c_package_dep_spec_error, "%s", dynamic_cast<const paludis::PackageDepSpecError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::AmbiguousPackageNameError *>(&ee))
{
VALUE ex_args[2];
ex_args[0] = rb_str_new2(dynamic_cast<const paludis::AmbiguousPackageNameError *>(&ee)->message().c_str());
ex_args[1] = rb_ary_new();
const AmbiguousPackageNameError * e = dynamic_cast<const paludis::AmbiguousPackageNameError *>(&ee);
for (AmbiguousPackageNameError::OptionsConstIterator f(e->begin_options()), f_end(e->end_options()) ;
f != f_end ; ++f)
rb_ary_unshift(ex_args[1], rb_str_new2(stringify(*f).c_str()));
rb_exc_raise(rb_class_new_instance(2, ex_args, c_ambiguous_package_name_error));
}
else if (0 != dynamic_cast<const paludis::NoSuchPackageError *>(&ee))
rb_raise(c_no_such_package_error, "%s", dynamic_cast<const paludis::NoSuchPackageError *>(&ee)->message().c_str());
2011-02-06 15:11:22 +01:00
else if (0 != dynamic_cast<const paludis::NoSuchRepositoryError *>(&ee))
rb_raise(c_no_such_repository_error, "%s", dynamic_cast<const paludis::NoSuchRepositoryError *>(&ee)->message().c_str());
2006-11-30 16:01:23 +01:00
else if (0 != dynamic_cast<const paludis::ConfigFileError *>(&ee))
rb_raise(c_config_file_error, "%s", dynamic_cast<const paludis::ConfigFileError *>(&ee)->message().c_str());
2006-11-30 16:01:23 +01:00
else if (0 != dynamic_cast<const paludis::ConfigurationError *>(&ee))
rb_raise(c_configuration_error, "%s", dynamic_cast<const paludis::ConfigurationError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::ActionFailedError *>(&ee))
rb_raise(c_action_failed_error, "%s", dynamic_cast<const paludis::ActionFailedError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::ActionAbortedError *>(&ee))
rb_raise(c_action_aborted_error, "%s", dynamic_cast<const paludis::ActionAbortedError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::BadVersionOperatorError *>(&ee))
rb_raise(c_bad_version_operator_error, "%s", dynamic_cast<const paludis::BadVersionOperatorError *>(&ee)->message().c_str());
else if (0 != dynamic_cast<const paludis::Exception *>(&ee))
rb_raise(rb_eRuntimeError, "Caught paludis::Exception: %s (%s)",
dynamic_cast<const paludis::Exception *>(&ee)->message().c_str(), ee.what());
else
rb_raise(rb_eRuntimeError, "Unexpected std::exception: (%s)", ee.what());
}
std::string
paludis::ruby::value_case_to_RubyCase(const std::string & s)
{
if (s.empty())
return s;
bool upper_next(true);
std::string result;
for (std::string::size_type p(0), p_end(s.length()) ; p != p_end ; ++p)
{
2007-01-11 17:26:02 +01:00
if ('_' == s[p] || ' ' == s[p])
upper_next = true;
else if (upper_next)
{
result.append(std::string(1, toupper(s[p])));
upper_next = false;
}
else
result.append(std::string(1, s[p]));
}
return result;
}
VALUE
paludis::ruby::paludis_module()
{
return c_paludis_module;
}
2007-01-20 18:09:29 +01:00
/*
* call-seq:
* query -> String or Nil
*
* Our query.
*/
VALUE
2007-01-21 12:19:43 +01:00
has_query_property_error_query(VALUE self)
2007-01-20 18:09:29 +01:00
{
return rb_attr_get(self, rb_intern("query"));
}
2007-11-07 10:27:51 +01:00
/*
* call-seq:
* failures -> Array
*
* Our failures
*/
VALUE
fetch_action_error_failures(VALUE self)
{
return rb_attr_get(self, rb_intern("failures"));
}
static VALUE
ambiguous_package_name_error_init(int argc, VALUE* argv, VALUE self)
{
VALUE options;
options = (argc > 1) ? argv[--argc] : Qnil;
rb_call_super(argc, argv);
rb_iv_set(self, "options", options);
return self;
}
/*
* call-seq:
* options -> Array
*
* Our options
*/
VALUE
ambiguous_package_name_error_failures(VALUE self)
{
return rb_attr_get(self, rb_intern("options"));
}
void PALUDIS_VISIBLE paludis::ruby::init()
{
/*
* Defined in create_ruby_doc.rb
*/
c_paludis_module = rb_define_module("Paludis");
c_name_error = rb_define_class_under(c_paludis_module, "NameError", rb_eRuntimeError);
c_set_name_error = rb_define_class_under(c_paludis_module, "SetNameError", c_name_error);
c_category_name_part_error = rb_define_class_under(c_paludis_module, "CategoryNamePartError", c_name_error);
c_package_name_part_error = rb_define_class_under(c_paludis_module, "PackageNamePartError", c_name_error);
c_bad_version_spec_error = rb_define_class_under(c_paludis_module, "BadVersionSpecError", c_name_error);
2007-02-22 02:16:22 +01:00
c_package_dep_spec_error = rb_define_class_under(c_paludis_module, "PackageDepSpecError", rb_eRuntimeError);
c_no_such_package_error = rb_define_class_under(c_paludis_module, "NoSuchPackageError", rb_eRuntimeError);
c_no_such_repository_error = rb_define_class_under(c_paludis_module, "NoSuchRepositoryError", rb_eRuntimeError);
c_configuration_error = rb_define_class_under(c_paludis_module, "ConfigurationError", rb_eRuntimeError);
c_config_file_error = rb_define_class_under(c_paludis_module, "ConfigFileError", c_configuration_error);
2007-11-07 10:27:51 +01:00
/*
* Document-class: Paludis::ActionFailedError
2007-11-07 10:27:51 +01:00
*/
c_action_failed_error = rb_define_class_under(c_paludis_module, "ActionFailedError", rb_eRuntimeError);
2007-11-07 10:27:51 +01:00
/*
* Document-class: Paludis::ActionAbortedError
2007-11-07 10:27:51 +01:00
*/
c_action_aborted_error = rb_define_class_under(c_paludis_module, "ActionAbortedError", rb_eRuntimeError);
2007-11-07 10:27:51 +01:00
/*
* Document-class: Paludis::AmbiguousPackageNameError
*
* Thrown if an Environment query results in more than one matching Package.
*/
c_ambiguous_package_name_error = rb_define_class_under(c_paludis_module, "AmbiguousPackageNameError", rb_eRuntimeError);
rb_define_method(c_ambiguous_package_name_error, "initialize", RUBY_FUNC_CAST(&ambiguous_package_name_error_init), -1);
rb_define_method(c_ambiguous_package_name_error, "options", RUBY_FUNC_CAST(&ambiguous_package_name_error_failures), 0);
/*
* Document-class: Paludis::GotASetNotAPackageDepSpec
*
* Thrown if parse_user_package_dep_spec gets a set.
*/
c_got_a_set_not_a_package_dep_spec = rb_define_class_under(c_paludis_module, "GotASetNotAPackageDepSpec",
rb_eRuntimeError);
/*
* Document-class: Paludis::BadVersionOperatorError
*
* Thrown if a bad version operator is encountered
*/
c_bad_version_operator_error = rb_define_class_under(c_paludis_module, "BadVersionOperatorError", rb_eRuntimeError);
2011-01-06 14:21:13 +01:00
rb_define_module_function(c_paludis_module, "match_package", RUBY_FUNC_CAST(&paludis_match_package), 5);
rb_define_module_function(c_paludis_module, "match_package_in_set", RUBY_FUNC_CAST(&paludis_match_package_in_set), 4);
rb_define_module_function(c_paludis_module, "version_spec_comparator", RUBY_FUNC_CAST(&paludis_version_spec_comparator), 3);
rb_define_const(c_paludis_module, "Version", INT2FIX(PALUDIS_VERSION));
rb_define_const(c_paludis_module, "VersionMajor", INT2FIX(PALUDIS_VERSION_MAJOR));
rb_define_const(c_paludis_module, "VersionMinor", INT2FIX(PALUDIS_VERSION_MINOR));
rb_define_const(c_paludis_module, "VersionMicro", INT2FIX(PALUDIS_VERSION_MICRO));
rb_define_const(c_paludis_module, "VersionSuffix",
rb_str_new2(stringify(PALUDIS_VERSION_SUFFIX).c_str()));
rb_define_const(c_paludis_module, "GitHead",
rb_str_new2(stringify(PALUDIS_GIT_HEAD).c_str()));
RegisterRubyClass::get_instance()->execute();
}
2008-10-24 10:32:40 +02:00
bool
paludis::ruby::value_to_bool(VALUE v)
{
if (Qfalse == v || Qnil == v)
return false;
return true;
}
VALUE
paludis::ruby::bool_to_value(bool b)
{
return b ? Qtrue : Qfalse;
}
MatchPackageOptions
paludis::ruby::value_to_match_package_options(VALUE v)
{
MatchPackageOptions o;
2009-03-29 09:49:19 +02:00
for (int i(0) ; i < RARRAY_LEN(v) ; ++i)
{
VALUE entry(rb_ary_entry(v, i));
Check_Type(entry, T_SYMBOL);
2011-05-19 15:20:48 +02:00
if (SYM2ID(entry) == rb_intern("ignore_additional_requirements"))
o += mpo_ignore_additional_requirements;
else
2013-09-08 09:32:58 +02:00
rb_raise(rb_eArgError, "Unknown MatchPackageOptions option '%s'", RSTRING_PTR(rb_obj_as_string(entry)));
}
return o;
}
VALUE
paludis::ruby::match_package_options_to_value(const MatchPackageOptions & o)
{
VALUE a(rb_ary_new());
2011-05-19 15:20:48 +02:00
if (o[mpo_ignore_additional_requirements])
rb_ary_push(a, ID2SYM(rb_intern("ignore_additional_requirements")));
return a;
}