class Paludis::FakeRepositoryBase

A FakeRepositoryBase is a Repository subclass whose subclasses are used for various test cases.

Public Instance Methods

add_category(category_name) → Nil click to toggle source

Add a category.

VALUE
    fake_repository_base_add_category(VALUE self, VALUE category)
    {
        try
        {
            std::shared_ptr<FakeRepositoryBase> repo(value_to_fake_repository_base(self));
            std::string cat_str(StringValuePtr(category));
            repo->add_category(CategoryNamePart(cat_str));
            return Qnil;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     add_package(qualified_package_name) -> Nil
     *
     * Add a package, and a category if necessary.
     */
    VALUE
    fake_repository_base_add_package(VALUE self, VALUE qpn)
    {
        try
        {
            std::shared_ptr<FakeRepositoryBase> repo(value_to_fake_repository_base(self));
            QualifiedPackageName name(value_to_qualified_package_name(qpn));
            repo->add_package(name);
            return Qnil;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     add_version(qualified_package_name, version_spec) -> PackageID
     *     add_version(category_name, package_name, version_string) -> PackageID
     *     add_version(category_name, package_name, version_string, slot) -> PackageID
     *
     * Add a version, and a package and category if necessary, and set some
     * default values for its metadata, and return said metadata.
     */
    VALUE
    fake_repository_base_add_version(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            std::shared_ptr<FakeRepositoryBase> repo(value_to_fake_repository_base(self));
            std::shared_ptr<FakePackageID> pkg;

            switch (argc)
            {
                case 2: {
                    QualifiedPackageName qpn(value_to_qualified_package_name(argv[0]));
                    VersionSpec ver(value_to_version_spec(argv[1]));
                    pkg = repo->add_version(qpn, ver);
                    break;
                }

                case 3: {
                    std::string cat(StringValuePtr(argv[0]));
                    std::string name(StringValuePtr(argv[1]));
                    std::string ver(StringValuePtr(argv[2]));
                    pkg = repo->add_version(cat, name, ver);
                    break;
                }

                case 4: {
                    std::string cat(StringValuePtr(argv[0]));
                    std::string name(StringValuePtr(argv[1]));
                    std::string ver(StringValuePtr(argv[2]));
                    std::string slot(StringValuePtr(argv[3]));
                    pkg = repo->add_version(cat, name, ver);
                    pkg->set_slot(SlotName(slot));
                    break;
                }

                default:
                    rb_raise(rb_eArgError, "FakeRepositoryBase.add_version expects two or three arguments, but got %d", argc);
            }

            return package_id_to_value(pkg);
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    VALUE
    fake_repository_init(int, VALUE*, VALUE self)
    {
        return self;
    }

    /*
     * call-seq:
     *     FakeRepository.new(environment, repo_name) -> FakeRepository
     *
     * Create a new FakeRepository.
     */
    VALUE
    fake_repository_new(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            if (2 != argc)
                rb_raise(rb_eArgError, "FakeRepository.new expects two arguments, but got %d", argc);

            std::shared_ptr<Repository> * r = new std::shared_ptr<Repository>(std::make_shared<FakeRepository>(
                        make_named_values<FakeRepositoryParams>(
                            n::environment() = value_to_environment(argv[0]).get(),
                            n::name() = RepositoryName(StringValuePtr(argv[1])))));
            VALUE tdata(Data_Wrap_Struct(self, 0, &Common<std::shared_ptr<Repository> >::free, r));
            rb_obj_call_init(tdata, argc, argv);
            return tdata;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     FakeInstalledRepository.new(environment, repo_name) -> FakeInstalledRepository
     *
     * Create a new FakeInstalledRepository.
     */
    VALUE
    fake_installed_repository_new(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            if (2 != argc)
                rb_raise(rb_eArgError, "FakeInstalledRepository.new expects two arguments, but got %d", argc);

            std::shared_ptr<Repository> * r = new std::shared_ptr<Repository>(new
                    FakeInstalledRepository(make_named_values<FakeInstalledRepositoryParams>(
                            n::environment() = value_to_environment(argv[0]).get(),
                            n::name() = RepositoryName(StringValuePtr(argv[1])),
                            n::suitable_destination() = true,
                            n::supports_uninstall() = true
                        )));
            VALUE tdata(Data_Wrap_Struct(self, 0, &Common<std::shared_ptr<Repository> >::free, r));
            rb_obj_call_init(tdata, argc, argv);
            return tdata;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     [String] -> MetadataKey or Nil
     *
     * The named metadata key.
     */
    VALUE
    repository_subscript(VALUE self, VALUE raw_name)
    {
        std::shared_ptr<const Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<const Repository>, self_ptr);
        Repository::MetadataConstIterator it((*self_ptr)->find_metadata(StringValuePtr(raw_name)));
        if ((*self_ptr)->end_metadata() == it)
            return Qnil;
        return metadata_key_to_value(*it);
    }

    /*
     * call-seq:
     *     each_metadata {|key| block } -> Nil
     *
     * Our metadata.
     */
    VALUE
    repository_each_metadata(VALUE self)
    {
        std::shared_ptr<Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
        for (Repository::MetadataConstIterator it((*self_ptr)->begin_metadata()),
                it_end((*self_ptr)->end_metadata()); it_end != it; ++it)
        {
            VALUE val(metadata_key_to_value(*it));
            if (Qnil != val)
                rb_yield(val);
        }
            return Qnil;
    }

    template <typename T_, const std::shared_ptr<const T_> (Repository::* m_) () const>
    struct RepositoryKey
    {
        static VALUE
        fetch(VALUE self)
        {
            std::shared_ptr<Repository> * self_ptr;
            Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
            return (((**self_ptr).*m_)()) ? metadata_key_to_value(((**self_ptr).*m_)()) : Qnil;
        }
    };

    /*
     * call-seq:
     *     get_environment_variable(package_id, environment_variable) -> String
     *
     * Query an environment variable.
     */
    VALUE
    repository_get_environment_variable(VALUE self, VALUE pid, VALUE ev)
    {
        std::shared_ptr<Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
        if ((**self_ptr).environment_variable_interface())
            return rb_str_new2((**self_ptr).environment_variable_interface()->get_environment_variable(
                        value_to_package_id(pid),
                        StringValuePtr(ev)).c_str());
        return Qnil;
    }

    void do_register_repository()
    {
        /*
         * Document-class: Paludis::Repository
         *
         * A Repository provides a representation of a physical repository to an Environment.
         */
        c_repository = rb_define_class_under(c_paludis_module, "Repository", rb_cObject);
        rb_funcall(c_repository, rb_intern("private_class_method"), 1, rb_str_new2("new"));
        rb_define_method(c_repository, "name", repository_name, 0);

        rb_define_method(c_repository, "has_category_named?", repository_has_category_named, 1);
        rb_define_method(c_repository, "has_package_named?", repository_has_package_named, 1);

        rb_define_method(c_repository, "category_names", repository_category_names, 0);
        rb_define_method(c_repository, "category_names_containing_package",                repository_category_names_containing_package, 1);
        rb_define_method(c_repository, "package_names", repository_package_names, 1);
        rb_define_method(c_repository, "package_ids", repository_package_ids, 1);

        rb_define_method(c_repository, "environment_variable_interface", template_methods, 0);
        rb_define_method(c_repository, "some_ids_might_support_action", repository_some_ids_might_support_action, 1);

        rb_define_method(c_repository, "[]", repository_subscript, 1);
        rb_define_method(c_repository, "each_metadata", repository_each_metadata, 0);
        rb_define_method(c_repository, "format_key",                RepositoryKey<MetadataValueKey<std::string> , Repository::format_key>::fetch, 0);
        rb_define_method(c_repository, "location_key",                template_methods, 0);
        rb_define_method(c_repository, "installed_root_key",                template_methods, 0);
        rb_define_method(c_repository, "get_environment_variable", repository_get_environment_variable, 2);

        /*
         * Document-class: Paludis::FakeRepositoryBase
         *
         * A FakeRepositoryBase is a Repository subclass whose subclasses are used for
         * various test cases.
         */
        c_fake_repository_base = rb_define_class_under(c_paludis_module, "FakeRepositoryBase", c_repository);
        rb_funcall(c_fake_repository_base, rb_intern("private_class_method"), 1, rb_str_new2("new"));
        rb_define_method(c_fake_repository_base, "add_category", fake_repository_base_add_category, 1);
        rb_define_method(c_fake_repository_base, "add_package", fake_repository_base_add_package, 1);
        rb_define_method(c_fake_repository_base, "add_version", fake_repository_base_add_version, -1);

        /*
         * Document-class: Paludis::FakeRepository
         *
         * Fake repository for use in test cases.
         */
        c_fake_repository = rb_define_class_under(c_paludis_module, "FakeRepository", c_fake_repository_base);
        rb_define_singleton_method(c_fake_repository, "new", fake_repository_new, -1);
        rb_define_method(c_fake_repository, "initialize", fake_repository_init, -1);

        /*
         * Document-class: Paludis::FakeInstalledRepository
         *
         * Fake repository for use in test cases.
         */
        c_fake_installed_repository = rb_define_class_under(c_paludis_module, "FakeInstalledRepository", c_fake_repository_base);
        rb_define_singleton_method(c_fake_installed_repository, "new", fake_installed_repository_new, -1);
        rb_define_method(c_fake_installed_repository, "initialize", fake_repository_init, -1);
    }
}
add_package(qualified_package_name) → Nil click to toggle source

Add a package, and a category if necessary.

VALUE
    fake_repository_base_add_package(VALUE self, VALUE qpn)
    {
        try
        {
            std::shared_ptr<FakeRepositoryBase> repo(value_to_fake_repository_base(self));
            QualifiedPackageName name(value_to_qualified_package_name(qpn));
            repo->add_package(name);
            return Qnil;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     add_version(qualified_package_name, version_spec) -> PackageID
     *     add_version(category_name, package_name, version_string) -> PackageID
     *     add_version(category_name, package_name, version_string, slot) -> PackageID
     *
     * Add a version, and a package and category if necessary, and set some
     * default values for its metadata, and return said metadata.
     */
    VALUE
    fake_repository_base_add_version(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            std::shared_ptr<FakeRepositoryBase> repo(value_to_fake_repository_base(self));
            std::shared_ptr<FakePackageID> pkg;

            switch (argc)
            {
                case 2: {
                    QualifiedPackageName qpn(value_to_qualified_package_name(argv[0]));
                    VersionSpec ver(value_to_version_spec(argv[1]));
                    pkg = repo->add_version(qpn, ver);
                    break;
                }

                case 3: {
                    std::string cat(StringValuePtr(argv[0]));
                    std::string name(StringValuePtr(argv[1]));
                    std::string ver(StringValuePtr(argv[2]));
                    pkg = repo->add_version(cat, name, ver);
                    break;
                }

                case 4: {
                    std::string cat(StringValuePtr(argv[0]));
                    std::string name(StringValuePtr(argv[1]));
                    std::string ver(StringValuePtr(argv[2]));
                    std::string slot(StringValuePtr(argv[3]));
                    pkg = repo->add_version(cat, name, ver);
                    pkg->set_slot(SlotName(slot));
                    break;
                }

                default:
                    rb_raise(rb_eArgError, "FakeRepositoryBase.add_version expects two or three arguments, but got %d", argc);
            }

            return package_id_to_value(pkg);
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    VALUE
    fake_repository_init(int, VALUE*, VALUE self)
    {
        return self;
    }

    /*
     * call-seq:
     *     FakeRepository.new(environment, repo_name) -> FakeRepository
     *
     * Create a new FakeRepository.
     */
    VALUE
    fake_repository_new(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            if (2 != argc)
                rb_raise(rb_eArgError, "FakeRepository.new expects two arguments, but got %d", argc);

            std::shared_ptr<Repository> * r = new std::shared_ptr<Repository>(std::make_shared<FakeRepository>(
                        make_named_values<FakeRepositoryParams>(
                            n::environment() = value_to_environment(argv[0]).get(),
                            n::name() = RepositoryName(StringValuePtr(argv[1])))));
            VALUE tdata(Data_Wrap_Struct(self, 0, &Common<std::shared_ptr<Repository> >::free, r));
            rb_obj_call_init(tdata, argc, argv);
            return tdata;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     FakeInstalledRepository.new(environment, repo_name) -> FakeInstalledRepository
     *
     * Create a new FakeInstalledRepository.
     */
    VALUE
    fake_installed_repository_new(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            if (2 != argc)
                rb_raise(rb_eArgError, "FakeInstalledRepository.new expects two arguments, but got %d", argc);

            std::shared_ptr<Repository> * r = new std::shared_ptr<Repository>(new
                    FakeInstalledRepository(make_named_values<FakeInstalledRepositoryParams>(
                            n::environment() = value_to_environment(argv[0]).get(),
                            n::name() = RepositoryName(StringValuePtr(argv[1])),
                            n::suitable_destination() = true,
                            n::supports_uninstall() = true
                        )));
            VALUE tdata(Data_Wrap_Struct(self, 0, &Common<std::shared_ptr<Repository> >::free, r));
            rb_obj_call_init(tdata, argc, argv);
            return tdata;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     [String] -> MetadataKey or Nil
     *
     * The named metadata key.
     */
    VALUE
    repository_subscript(VALUE self, VALUE raw_name)
    {
        std::shared_ptr<const Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<const Repository>, self_ptr);
        Repository::MetadataConstIterator it((*self_ptr)->find_metadata(StringValuePtr(raw_name)));
        if ((*self_ptr)->end_metadata() == it)
            return Qnil;
        return metadata_key_to_value(*it);
    }

    /*
     * call-seq:
     *     each_metadata {|key| block } -> Nil
     *
     * Our metadata.
     */
    VALUE
    repository_each_metadata(VALUE self)
    {
        std::shared_ptr<Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
        for (Repository::MetadataConstIterator it((*self_ptr)->begin_metadata()),
                it_end((*self_ptr)->end_metadata()); it_end != it; ++it)
        {
            VALUE val(metadata_key_to_value(*it));
            if (Qnil != val)
                rb_yield(val);
        }
            return Qnil;
    }

    template <typename T_, const std::shared_ptr<const T_> (Repository::* m_) () const>
    struct RepositoryKey
    {
        static VALUE
        fetch(VALUE self)
        {
            std::shared_ptr<Repository> * self_ptr;
            Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
            return (((**self_ptr).*m_)()) ? metadata_key_to_value(((**self_ptr).*m_)()) : Qnil;
        }
    };

    /*
     * call-seq:
     *     get_environment_variable(package_id, environment_variable) -> String
     *
     * Query an environment variable.
     */
    VALUE
    repository_get_environment_variable(VALUE self, VALUE pid, VALUE ev)
    {
        std::shared_ptr<Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
        if ((**self_ptr).environment_variable_interface())
            return rb_str_new2((**self_ptr).environment_variable_interface()->get_environment_variable(
                        value_to_package_id(pid),
                        StringValuePtr(ev)).c_str());
        return Qnil;
    }

    void do_register_repository()
    {
        /*
         * Document-class: Paludis::Repository
         *
         * A Repository provides a representation of a physical repository to an Environment.
         */
        c_repository = rb_define_class_under(c_paludis_module, "Repository", rb_cObject);
        rb_funcall(c_repository, rb_intern("private_class_method"), 1, rb_str_new2("new"));
        rb_define_method(c_repository, "name", repository_name, 0);

        rb_define_method(c_repository, "has_category_named?", repository_has_category_named, 1);
        rb_define_method(c_repository, "has_package_named?", repository_has_package_named, 1);

        rb_define_method(c_repository, "category_names", repository_category_names, 0);
        rb_define_method(c_repository, "category_names_containing_package",                repository_category_names_containing_package, 1);
        rb_define_method(c_repository, "package_names", repository_package_names, 1);
        rb_define_method(c_repository, "package_ids", repository_package_ids, 1);

        rb_define_method(c_repository, "environment_variable_interface", template_methods, 0);
        rb_define_method(c_repository, "some_ids_might_support_action", repository_some_ids_might_support_action, 1);

        rb_define_method(c_repository, "[]", repository_subscript, 1);
        rb_define_method(c_repository, "each_metadata", repository_each_metadata, 0);
        rb_define_method(c_repository, "format_key",                RepositoryKey<MetadataValueKey<std::string> , Repository::format_key>::fetch, 0);
        rb_define_method(c_repository, "location_key",                template_methods, 0);
        rb_define_method(c_repository, "installed_root_key",                template_methods, 0);
        rb_define_method(c_repository, "get_environment_variable", repository_get_environment_variable, 2);

        /*
         * Document-class: Paludis::FakeRepositoryBase
         *
         * A FakeRepositoryBase is a Repository subclass whose subclasses are used for
         * various test cases.
         */
        c_fake_repository_base = rb_define_class_under(c_paludis_module, "FakeRepositoryBase", c_repository);
        rb_funcall(c_fake_repository_base, rb_intern("private_class_method"), 1, rb_str_new2("new"));
        rb_define_method(c_fake_repository_base, "add_category", fake_repository_base_add_category, 1);
        rb_define_method(c_fake_repository_base, "add_package", fake_repository_base_add_package, 1);
        rb_define_method(c_fake_repository_base, "add_version", fake_repository_base_add_version, -1);

        /*
         * Document-class: Paludis::FakeRepository
         *
         * Fake repository for use in test cases.
         */
        c_fake_repository = rb_define_class_under(c_paludis_module, "FakeRepository", c_fake_repository_base);
        rb_define_singleton_method(c_fake_repository, "new", fake_repository_new, -1);
        rb_define_method(c_fake_repository, "initialize", fake_repository_init, -1);

        /*
         * Document-class: Paludis::FakeInstalledRepository
         *
         * Fake repository for use in test cases.
         */
        c_fake_installed_repository = rb_define_class_under(c_paludis_module, "FakeInstalledRepository", c_fake_repository_base);
        rb_define_singleton_method(c_fake_installed_repository, "new", fake_installed_repository_new, -1);
        rb_define_method(c_fake_installed_repository, "initialize", fake_repository_init, -1);
    }
}
add_version(qualified_package_name, version_spec) → PackageID click to toggle source
add_version(category_name, package_name, version_string) → PackageID
add_version(category_name, package_name, version_string, slot) → PackageID

Add a version, and a package and category if necessary, and set some default values for its metadata, and return said metadata.

VALUE
    fake_repository_base_add_version(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            std::shared_ptr<FakeRepositoryBase> repo(value_to_fake_repository_base(self));
            std::shared_ptr<FakePackageID> pkg;

            switch (argc)
            {
                case 2: {
                    QualifiedPackageName qpn(value_to_qualified_package_name(argv[0]));
                    VersionSpec ver(value_to_version_spec(argv[1]));
                    pkg = repo->add_version(qpn, ver);
                    break;
                }

                case 3: {
                    std::string cat(StringValuePtr(argv[0]));
                    std::string name(StringValuePtr(argv[1]));
                    std::string ver(StringValuePtr(argv[2]));
                    pkg = repo->add_version(cat, name, ver);
                    break;
                }

                case 4: {
                    std::string cat(StringValuePtr(argv[0]));
                    std::string name(StringValuePtr(argv[1]));
                    std::string ver(StringValuePtr(argv[2]));
                    std::string slot(StringValuePtr(argv[3]));
                    pkg = repo->add_version(cat, name, ver);
                    pkg->set_slot(SlotName(slot));
                    break;
                }

                default:
                    rb_raise(rb_eArgError, "FakeRepositoryBase.add_version expects two or three arguments, but got %d", argc);
            }

            return package_id_to_value(pkg);
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    VALUE
    fake_repository_init(int, VALUE*, VALUE self)
    {
        return self;
    }

    /*
     * call-seq:
     *     FakeRepository.new(environment, repo_name) -> FakeRepository
     *
     * Create a new FakeRepository.
     */
    VALUE
    fake_repository_new(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            if (2 != argc)
                rb_raise(rb_eArgError, "FakeRepository.new expects two arguments, but got %d", argc);

            std::shared_ptr<Repository> * r = new std::shared_ptr<Repository>(std::make_shared<FakeRepository>(
                        make_named_values<FakeRepositoryParams>(
                            n::environment() = value_to_environment(argv[0]).get(),
                            n::name() = RepositoryName(StringValuePtr(argv[1])))));
            VALUE tdata(Data_Wrap_Struct(self, 0, &Common<std::shared_ptr<Repository> >::free, r));
            rb_obj_call_init(tdata, argc, argv);
            return tdata;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     FakeInstalledRepository.new(environment, repo_name) -> FakeInstalledRepository
     *
     * Create a new FakeInstalledRepository.
     */
    VALUE
    fake_installed_repository_new(int argc, VALUE* argv, VALUE self)
    {
        try
        {
            if (2 != argc)
                rb_raise(rb_eArgError, "FakeInstalledRepository.new expects two arguments, but got %d", argc);

            std::shared_ptr<Repository> * r = new std::shared_ptr<Repository>(new
                    FakeInstalledRepository(make_named_values<FakeInstalledRepositoryParams>(
                            n::environment() = value_to_environment(argv[0]).get(),
                            n::name() = RepositoryName(StringValuePtr(argv[1])),
                            n::suitable_destination() = true,
                            n::supports_uninstall() = true
                        )));
            VALUE tdata(Data_Wrap_Struct(self, 0, &Common<std::shared_ptr<Repository> >::free, r));
            rb_obj_call_init(tdata, argc, argv);
            return tdata;
        }
        catch (const std::exception & e)
        {
            exception_to_ruby_exception(e);
        }
    }

    /*
     * call-seq:
     *     [String] -> MetadataKey or Nil
     *
     * The named metadata key.
     */
    VALUE
    repository_subscript(VALUE self, VALUE raw_name)
    {
        std::shared_ptr<const Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<const Repository>, self_ptr);
        Repository::MetadataConstIterator it((*self_ptr)->find_metadata(StringValuePtr(raw_name)));
        if ((*self_ptr)->end_metadata() == it)
            return Qnil;
        return metadata_key_to_value(*it);
    }

    /*
     * call-seq:
     *     each_metadata {|key| block } -> Nil
     *
     * Our metadata.
     */
    VALUE
    repository_each_metadata(VALUE self)
    {
        std::shared_ptr<Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
        for (Repository::MetadataConstIterator it((*self_ptr)->begin_metadata()),
                it_end((*self_ptr)->end_metadata()); it_end != it; ++it)
        {
            VALUE val(metadata_key_to_value(*it));
            if (Qnil != val)
                rb_yield(val);
        }
            return Qnil;
    }

    template <typename T_, const std::shared_ptr<const T_> (Repository::* m_) () const>
    struct RepositoryKey
    {
        static VALUE
        fetch(VALUE self)
        {
            std::shared_ptr<Repository> * self_ptr;
            Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
            return (((**self_ptr).*m_)()) ? metadata_key_to_value(((**self_ptr).*m_)()) : Qnil;
        }
    };

    /*
     * call-seq:
     *     get_environment_variable(package_id, environment_variable) -> String
     *
     * Query an environment variable.
     */
    VALUE
    repository_get_environment_variable(VALUE self, VALUE pid, VALUE ev)
    {
        std::shared_ptr<Repository> * self_ptr;
        Data_Get_Struct(self, std::shared_ptr<Repository>, self_ptr);
        if ((**self_ptr).environment_variable_interface())
            return rb_str_new2((**self_ptr).environment_variable_interface()->get_environment_variable(
                        value_to_package_id(pid),
                        StringValuePtr(ev)).c_str());
        return Qnil;
    }

    void do_register_repository()
    {
        /*
         * Document-class: Paludis::Repository
         *
         * A Repository provides a representation of a physical repository to an Environment.
         */
        c_repository = rb_define_class_under(c_paludis_module, "Repository", rb_cObject);
        rb_funcall(c_repository, rb_intern("private_class_method"), 1, rb_str_new2("new"));
        rb_define_method(c_repository, "name", repository_name, 0);

        rb_define_method(c_repository, "has_category_named?", repository_has_category_named, 1);
        rb_define_method(c_repository, "has_package_named?", repository_has_package_named, 1);

        rb_define_method(c_repository, "category_names", repository_category_names, 0);
        rb_define_method(c_repository, "category_names_containing_package",                repository_category_names_containing_package, 1);
        rb_define_method(c_repository, "package_names", repository_package_names, 1);
        rb_define_method(c_repository, "package_ids", repository_package_ids, 1);

        rb_define_method(c_repository, "environment_variable_interface", template_methods, 0);
        rb_define_method(c_repository, "some_ids_might_support_action", repository_some_ids_might_support_action, 1);

        rb_define_method(c_repository, "[]", repository_subscript, 1);
        rb_define_method(c_repository, "each_metadata", repository_each_metadata, 0);
        rb_define_method(c_repository, "format_key",                RepositoryKey<MetadataValueKey<std::string> , Repository::format_key>::fetch, 0);
        rb_define_method(c_repository, "location_key",                template_methods, 0);
        rb_define_method(c_repository, "installed_root_key",                template_methods, 0);
        rb_define_method(c_repository, "get_environment_variable", repository_get_environment_variable, 2);

        /*
         * Document-class: Paludis::FakeRepositoryBase
         *
         * A FakeRepositoryBase is a Repository subclass whose subclasses are used for
         * various test cases.
         */
        c_fake_repository_base = rb_define_class_under(c_paludis_module, "FakeRepositoryBase", c_repository);
        rb_funcall(c_fake_repository_base, rb_intern("private_class_method"), 1, rb_str_new2("new"));
        rb_define_method(c_fake_repository_base, "add_category", fake_repository_base_add_category, 1);
        rb_define_method(c_fake_repository_base, "add_package", fake_repository_base_add_package, 1);
        rb_define_method(c_fake_repository_base, "add_version", fake_repository_base_add_version, -1);

        /*
         * Document-class: Paludis::FakeRepository
         *
         * Fake repository for use in test cases.
         */
        c_fake_repository = rb_define_class_under(c_paludis_module, "FakeRepository", c_fake_repository_base);
        rb_define_singleton_method(c_fake_repository, "new", fake_repository_new, -1);
        rb_define_method(c_fake_repository, "initialize", fake_repository_init, -1);

        /*
         * Document-class: Paludis::FakeInstalledRepository
         *
         * Fake repository for use in test cases.
         */
        c_fake_installed_repository = rb_define_class_under(c_paludis_module, "FakeInstalledRepository", c_fake_repository_base);
        rb_define_singleton_method(c_fake_installed_repository, "new", fake_installed_repository_new, -1);
        rb_define_method(c_fake_installed_repository, "initialize", fake_repository_init, -1);
    }
}