/* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* * Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011 Ciaran McCreesh * Copyright (c) 2007, 2008 Richard Brown * * 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 #include #include #include #include #include #include #include #include using namespace paludis; using namespace paludis::ruby; namespace { static VALUE c_environment; static VALUE c_paludis_environment; static VALUE c_test_environment; static VALUE c_environment_factory; /* * call-seq: * [](Selection) -> Array of PackageID * * Fetch PackageID instances using the supplied Selection. */ VALUE environment_square_brackets(VALUE self, VALUE selection) { try { std::shared_ptr ids(value_to_environment(self)->operator[] (value_to_selection(selection))); VALUE result(rb_ary_new()); for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ; i != i_end ; ++i) rb_ary_push(result, package_id_to_value(*i)); return result; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * set(set_name) -> DepSpec * * Fetch a named package set as a DepSpec. */ VALUE environment_set(VALUE self, VALUE set_name) { try { SetName s(StringValuePtr(set_name)); std::shared_ptr set = (value_to_environment(self)->set(s)); if (set) return dep_tree_to_value(set); else return Qnil; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * accept_license(license, package_id) -> true or false * * Do we accept a particular license for a particular package? */ VALUE environment_accept_license(VALUE self, VALUE license, VALUE p) { try { return value_to_environment(self)->accept_license( std::string(StringValuePtr(license)), (value_to_package_id(p))) ? Qtrue : Qfalse; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * accept_keywords(keywords, package_id) -> true or false * * Do we accept any of the specified keywords for a particular package? */ VALUE environment_accept_keywords(VALUE self, VALUE keywords, VALUE p) { if (rb_obj_is_kind_of(keywords, rb_cArray)) { try { std::shared_ptr knc (std::make_shared()); long len = NUM2LONG(rb_funcall(keywords,rb_intern("length"),0)); for (long i = 0; i < len; i++) { // Stupid macros won't let me do it on one line. VALUE kw = rb_ary_entry(keywords, i); knc->insert(KeywordName(StringValuePtr(kw))); } return value_to_environment(self)->accept_keywords(knc, value_to_package_id(p)) ? Qtrue : Qfalse; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } else { rb_raise(rb_eTypeError, "Can't convert %s into Array", rb_obj_classname(keywords)); } } /* * call-seq: * mirrors(mirror_name) -> Array * * Return the mirror URI prefixes for a named mirror. */ VALUE environment_mirrors(VALUE self, VALUE mirror) { try { VALUE result(rb_ary_new()); std::shared_ptr m(value_to_environment(self)->mirrors(StringValuePtr(mirror))); for (MirrorsSequence::ConstIterator i(m->begin()), i_end(m->end()) ; i != i_end ; i++) rb_ary_push(result, rb_str_new2(stringify(*i).c_str())); return result; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } VALUE environment_distribution(VALUE self) { return rb_str_new2(value_to_environment(self)->distribution().c_str()); } template (Environment::* m_) () const> struct EnvironmentKey { static VALUE fetch(VALUE self) { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); return (((**self_ptr).*m_)()) ? metadata_key_to_value(((**self_ptr).*m_)()) : Qnil; } }; std::shared_ptr value_to_paludis_environment(VALUE v) { if (rb_obj_is_kind_of(v, c_paludis_environment)) { std::shared_ptr * v_ptr; Data_Get_Struct(v, std::shared_ptr, v_ptr); return std::static_pointer_cast(*v_ptr); } else { rb_raise(rb_eTypeError, "Can't convert %s into PaludisEnvironment", rb_obj_classname(v)); } } VALUE paludis_environment_init(int, VALUE*, VALUE self) { return self; } /* * call-seq: * PaludisEnvironment.new -> PaludisEnvironment * PaludisEnvironment.new(config_suffix) -> PaludisEnvironment * * Create a new PaludisEnvironment, with the specified config suffix if any, otherwise the empty suffix. */ VALUE paludis_environment_new(int argc, VALUE* argv, VALUE self) { try { std::string config_suffix; if (1 == argc) config_suffix = StringValuePtr(argv[0]); else if (0 != argc) rb_raise(rb_eArgError, "PaludisEnvironment.new expects one or zero arguments, but got %d", argc); std::shared_ptr * e = new std::shared_ptr(std::make_shared(config_suffix)); VALUE tdata(Data_Wrap_Struct(self, 0, &Common >::free, e)); rb_obj_call_init(tdata, argc, argv); return tdata; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * TestEnvironment.new -> TestEnvironment * * Create a new TestEnvironment. */ VALUE test_environment_new(VALUE self) { try { std::shared_ptr * e = new std::shared_ptr(std::make_shared()); VALUE tdata(Data_Wrap_Struct(self, 0, &Common >::free, e)); rb_obj_call_init(tdata, 0, &self); return tdata; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * config_dir -> String * * Configuration directory used by this PaludisEnvironment. */ VALUE paludis_environment_config_dir(VALUE self) { return rb_str_new2(value_to_paludis_environment(self)->config_dir().c_str()); } /* * call-seq: * create(spec) -> Environment * * Create an environment from the given spec. * A spec consisits of class:suffix both of which may be omitted. class is the environment class, * e.g. paludis or portage, suffix is the configuration directory suffix. * */ VALUE environment_factory_create(VALUE, VALUE spec) { try { std::shared_ptr * e = new std::shared_ptr(EnvironmentFactory::get_instance()->create( StringValuePtr(spec))); VALUE tdata(Data_Wrap_Struct(c_environment, 0, &Common >::free, e)); return tdata; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * fetch_unique_qualified_package_name(package_name) -> QualifiedPackageName * fetch_unique_qualified_package_name(package_name, filter) -> QualifiedPackageName * * Disambiguate a package name. If a filter is specified, limit * the potential results to packages that match. */ VALUE environment_fetch_unique_qualified_package_name(int argc, VALUE *argv, VALUE self) { try { if (1 == argc || 2 == argc) { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); return qualified_package_name_to_value((*self_ptr)->fetch_unique_qualified_package_name( PackageNamePart(StringValuePtr(argv[0])), 2 == argc ? value_to_filter(argv[1]) : filter::All())); } else rb_raise(rb_eArgError, "fetch_unique_qualified_package_name expects one or two arguments, but got %d",argc); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * repositories -> Array * repositories {|repository| block } -> Nil * * Returns all the repositories in the package database, either as an Array, or as * the parameters to a block. */ VALUE environment_repositories(VALUE self) { try { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); if (rb_block_given_p()) { for (Environment::RepositoryConstIterator r((*self_ptr)->begin_repositories()), r_end((*self_ptr)->end_repositories()) ; r != r_end ; ++r) rb_yield(repository_to_value(*r)); return Qnil; } VALUE result(rb_ary_new()); for (Environment::RepositoryConstIterator r((*self_ptr)->begin_repositories()), r_end((*self_ptr)->end_repositories()) ; r != r_end ; ++r) rb_ary_push(result, repository_to_value(*r)); return result; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * fetch_repository(repository_name) -> Repository * * Fetch a named repository. */ VALUE environment_fetch_repository(VALUE self, VALUE name) { try { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); return repository_to_value((*self_ptr)->fetch_repository(RepositoryName(StringValuePtr(name)))); } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * more_important_than(repository_name_a, repository_name_b) -> bool * * True if repository_name_a is more important than repository_name_b . */ VALUE environment_more_important_than(VALUE self, VALUE name1, VALUE name2) { try { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); return (*self_ptr)->more_important_than(RepositoryName(StringValuePtr(name1)), RepositoryName(StringValuePtr(name2))) ? Qtrue : Qfalse; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * has_repository_named?(repository_name) -> true or false * * Do we have a named repository? */ VALUE environment_has_repository_named(VALUE self, VALUE name) { try { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); return ((*self_ptr)->has_repository_named(RepositoryName(StringValuePtr(name)))) ? true : false; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } /* * call-seq: * add_repository(importance, repository) -> nil * * Add a repository. */ VALUE environment_add_repository(VALUE self, VALUE importance, VALUE repo_v) { try { std::shared_ptr * self_ptr; Data_Get_Struct(self, std::shared_ptr, self_ptr); std::shared_ptr repo(value_to_repository(repo_v)); (*self_ptr)->add_repository(NUM2INT(importance), repo); return Qnil; } catch (const std::exception & e) { exception_to_ruby_exception(e); } } void do_register_environment() { rb_require("singleton"); /* * Document-class: Paludis::Environment * * Represents a working environment, which contains an available packages database and provides * various methods for querying package visibility and options. */ c_environment = rb_define_class_under(paludis_module(), "Environment", rb_cObject); rb_funcall(c_environment, rb_intern("private_class_method"), 1, rb_str_new2("new")); rb_define_method(c_environment, "set", RUBY_FUNC_CAST(&environment_set), 1); rb_define_method(c_environment, "distribution", RUBY_FUNC_CAST(&environment_distribution), 0); rb_define_method(c_environment, "accept_license", RUBY_FUNC_CAST(&environment_accept_license), 2); rb_define_method(c_environment, "accept_keywords", RUBY_FUNC_CAST(&environment_accept_keywords), 2); rb_define_method(c_environment, "mirrors", RUBY_FUNC_CAST(&environment_mirrors), 1); rb_define_method(c_environment, "[]", RUBY_FUNC_CAST(&environment_square_brackets), 1); rb_define_method(c_environment, "format_key", RUBY_FUNC_CAST((&EnvironmentKey , &Environment::format_key>::fetch)), 0); rb_define_method(c_environment, "config_location_key", RUBY_FUNC_CAST((&EnvironmentKey, &Environment::config_location_key>::fetch)), 0); rb_define_method(c_environment, "preferred_root_key", RUBY_FUNC_CAST((&EnvironmentKey, &Environment::preferred_root_key>::fetch)), 0); rb_define_method(c_environment, "fetch_unique_qualified_package_name", RUBY_FUNC_CAST(&environment_fetch_unique_qualified_package_name), -1); rb_define_method(c_environment, "repositories", RUBY_FUNC_CAST(&environment_repositories), 0); rb_define_method(c_environment, "fetch_repository", RUBY_FUNC_CAST(&environment_fetch_repository), 1); rb_define_method(c_environment, "more_important_than", RUBY_FUNC_CAST(&environment_more_important_than), 2); rb_define_method(c_environment, "has_repository_named?", RUBY_FUNC_CAST(&environment_has_repository_named), 1); rb_define_method(c_environment, "add_repository", RUBY_FUNC_CAST(&environment_add_repository), 2); /* * Document-class: Paludis::PaludisEnvironment * * An Environment that corresponds to the normal operating evironment. */ c_paludis_environment = rb_define_class_under(paludis_module(), "PaludisEnvironment", c_environment); rb_define_singleton_method(c_paludis_environment, "new", RUBY_FUNC_CAST(&paludis_environment_new), -1); rb_define_method(c_paludis_environment, "initialize", RUBY_FUNC_CAST(&paludis_environment_init), -1); rb_define_method(c_paludis_environment, "config_dir", RUBY_FUNC_CAST(&paludis_environment_config_dir), 0); /* * Document-class: Paludis::TestEnvironment * * A crude test environment. */ c_test_environment = rb_define_class_under(paludis_module(), "TestEnvironment", c_environment); rb_define_singleton_method(c_test_environment, "new", RUBY_FUNC_CAST(&test_environment_new), 0); /* * Document-class: Paludis::EnvironmentFactory * * A class that holds methods to create environments. * * To access the default environment use create("") */ c_environment_factory = rb_define_class_under(paludis_module(), "EnvironmentFactory", rb_cObject); rb_funcall(rb_const_get(rb_cObject, rb_intern("Singleton")), rb_intern("included"), 1, c_environment_factory); rb_define_method(c_environment_factory, "create", RUBY_FUNC_CAST(&environment_factory_create), 1); } } std::shared_ptr paludis::ruby::value_to_environment(VALUE v) { if (rb_obj_is_kind_of(v, c_environment)) { std::shared_ptr * v_ptr; Data_Get_Struct(v, std::shared_ptr, v_ptr); return *v_ptr; } else { rb_raise(rb_eTypeError, "Can't convert %s into Environment", rb_obj_classname(v)); } } RegisterRubyClass::Register paludis_ruby_register_environment PALUDIS_ATTRIBUTE((used)) (&do_register_environment);