You can get a Subversion
trunk/ rather than working off a tarball. If you're
planning to submit patches, you'll have to do this.
It's best to start by skimming over the main program to get a feel for how everything fits together. The interface code is kept in the src/ directory, and library code is in paludis/ .
There are currently two APIs available:
A basic C++ application will look something like:
Compile this using
g++ -Wall -lpaludis
-lpaludisenvironments. If your compiler lacks tr1 support, you
may also need
The same application written in Ruby will look something like:
Notice how various Rubyisms (singleton styles, question mark methods, constants for enums) are used. The Ruby interface aims to be natural to Ruby programmers and behave like a Ruby library, rather than being an exact translation.
Make sure you can run both of these examples before reading on.
A number of common patterns are used throughout the code.
STL style iterator pairs crop up in various places. Where this happens, there is
usually a member typedef named
along with members named
end_foo. See TCppSL
if you are unfamiliar with this style.
The underlying iterator format is usually hidden from the library programmer by a
libwrapiter::ForwardIterator. This is to speed up compile times and to avoid breaking
lots of things when underlying data types change.
Ruby works better with blocks than external iterators. Thus, instead of providing
end_foo methods, Ruby classes typically have
foo member function that returns an array made from the
iterator range. This is slower, but much easier.
We make extensive use of
std::tr1::shared_ptr. Make sure you know how it
works. See TCppSLE.
This is all hidden in the Ruby interface. You shouldn't have to care about memory management.
Rather than using
std::string for package, category etc names, we have a wrapper
class template called
paludis::Validated, and a bunch of typedefs
paludis::SlotName etc). This gives a couple of benefits:
Ruby doesn't do static checking, so it just uses raw
instances for all of these.
Sometimes we need to pass around a collection of items. The
paludis::AssociativeCollection wrappers handle this.
They are passed around via smart pointers to avoid copying.
The basic classes are abstract. Use
paludis::SortedCollection::Concrete etc if you need
to make one yourself.
In Ruby these are converted to arrays.
Smart records are a bit smarter than Plain Old Data structs. They might define comparison operators and constructors. They're used in quite a few places. Try not to worry about how these work internally unless you want to get a very sore head.
Some smart records support named parameter constructors. A typical call to one of these looks like:
PackageDatabaseEntry my_pde(PackageDatabaseEntryParams::create() .package(QualifiedPackageName("app-editors/vim")) .version(VersionSpec("7.0.147")) .repository(RepositoryName("gentoo")));
Named parameters can be specified in any order.
Many types can be converted to a
std::string for display
template function will handle this. It also works for any internal and standard library data
type that can be written to a
At the heart of the Paludis API is a
paludis::Environment subclass instance. All
non-trivial clients will use one of the Environment subclasses as their starting
point for obtaining data (
Environment itself contains abstract members and cannot
be used directly).
classes should be used when user configuration is to be honoured. These classes are not usually
created directly; instead,
paludis::EnvironmentMaker is used to obtain an
std::string my_spec_string(...); std::tr1::shared_ptr<paludis::Environment> env( paludis::EnvironmentMaker::get_instance()-<make_from_spec(my_spec_string));
The specification string should usually be the command line parameter value for
--environment. An empty string will give the default
EnvironmentMaker, linking should include
In Ruby, instances must be obtained using
paludis::NoConfigEnvironment class should be used when user configuration should
not be read, and instead the repository should be from a single particular directory.
Multiple instances of this environment can be created if necessary.
NoConfigEnvironment, linking should include
In Ruby the class is
paludis::qa::QAEnvironment class is used for QA environments. There is also a
paludis::TestEnvironment class that is used in some test cases. These are less useful
for most client authors.
In Ruby the class for a QA environment is
Paludis::QA::QAEnvironment, there is
currently no Ruby wrapper for the test environment.
paludis::Environment has a
paludis::PackageDatabase, which can be obtained
PackageDatabase contains a number of
paludis::Repository subclass instances. These
can be obtained using the
paludis::PackageDatabase::end_repositories() pair or the
PackageDatabase also provides a number of utility functions.
can be used to fetch a
paludis::PackageDatabaseEntryCollection containing packages
matching a particular
can be used to convert a
paludis::PackageNamePart with no
In Ruby, the class is
Paludis::PackageDatabase and an instance can
only be obtained by calling
Rather than providing iterator pairs, repositories are available through the
repositories method, whose return value behaves like an array of
Paludis::Repository subclass instances. The
fetch_unique_qualified_package_name methods are available.
paludis::Repository class is an abstract base class representing a
paludis::Repository subclass provides various core functions,
along with various optional others based upon the repository's capabilities.
The commonly used subclasses are:
Repository creation is usually handled by the
paludis::Environment subclass and its
associated paludis::PackageDatabase. In Ruby, this is the only way to gain access
to a repository.
All repositories provide some basic functions for querying their contents. Commonly used
paludis::Repository::has_version(). These are available through Ruby; the has_ functions
have a question mark suffix as per Ruby convention.
Additional capabilities are available through optional interfaces. These can be accessed
via members named
and so on -- these members will either be a pointer to the interface or a zero
A full list of optional capabilities can be seen in the documentation for
from which paludis::Repository inherits.
In Ruby, this works a bit differently. Members that return either a self reference or nil are available for each interface. They are named as their C++ equivalents.@FOOTER@