example_dep_tag.cc

This example demonstrates how to handle dependency tags. It displays information about the 'security' and 'world' sets.

/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/** \file
 *
 * Example \ref example_dep_tag.cc "example_dep_tag.cc" .
 *
 * \ingroup g_dep_spec
 */

/** \example example_dep_tag.cc
 *
 * This example demonstrates how to handle dependency tags. It displays
 * information about the 'security' and 'world' sets.
 */

#include <paludis/paludis.hh>
#include "example_command_line.hh"
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <set>

using namespace paludis;
using namespace examples;

using std::cout;
using std::endl;
using std::setw;
using std::left;
using std::boolalpha;

/* We store a set of dep tag categories that we've seen. */
typedef std::set<std::string> SeenCategories;

namespace
{
    /* This visitor is used to display information about a tag. */
    class TagDisplayer
    {
        public:
            void visit(const DependencyDepTag & tag)
            {
                /* A DependencyDepTag is used during dependency resolution. It
                 * shows why a package is included on a DepList. It has three
                 * additional fields: an optional package ID that pulled in the
                 * entry, an optional dep spec that pulled in the dependency and
                 * an optional set of conditions upon which that dependency is
                 * active. The third field is not used here, since it is too
                 * complicated for this example. */
                if (tag.package_id())
                    cout << left << setw(20) << "        Package ID:" << " " << *tag.package_id() << endl;
                if (tag.dependency())
                    cout << left << setw(20) << "        Dependency:" << " " << *tag.dependency() << endl;
            }

            void visit(const GLSADepTag & tag)
            {
                /* A GLSADepTag is for security advisories. It carries one
                 * additional field, the GLSA's title. */
                cout << left << setw(20) << "        GLSA title:" << " " << tag.glsa_title() << endl;
            }

            void visit(const GeneralSetDepTag & tag)
            {
                /* A GeneralSetDepTag is for general package sets. It carries
                 * one additional field, the source (e.g. a repository or
                 * environment name). */
                cout << left << setw(20) << "        Source:" << " " << tag.source() << endl;
            }

            void visit(const TargetDepTag &)
            {
                /* A TargetDepTag is used to indicate explicit targets when
                 * resolving dependencies. It carries no extra information. */
            }
    };

    /* Display information about a named set. */
    void display_set(
            const std::tr1::shared_ptr<const Environment> & env,
            const SetName & name,
            SeenCategories & seen_categories)
    {
        std::tr1::shared_ptr<const SetSpecTree> set(env->set(name));

        /* Environment::set can return a zero pointer, if a set is not known. */
        if (! set)
            return;

        /* The set isn't necessarily flat. We use DepSpecFlattener to make it
         * so, rather than writing a full visitor ourselves. */
        DepSpecFlattener<SetSpecTree, PackageDepSpec> set_flat(env.get());
        set->root()->accept(set_flat);

        cout << "Set '" << name << "':" << endl;

        /* For each item... */
        for (DepSpecFlattener<SetSpecTree, PackageDepSpec>::ConstIterator s(set_flat.begin()),
                s_end(set_flat.end()) ; s != s_end ; ++s)
        {
            /* Ignore it, if it has no tag. */
            if (! (*s)->tag())
                continue;

            cout << "    " << **s << ": " << endl;

            /* All dep tags have short text and a category. As well as
             * displaying the category, we remember it for the categories
             * summary later on. */
            cout << left << setw(20) << "        Short text:" << " " << (*s)->tag()->short_text() << endl;
            cout << left << setw(20) << "        Category:" << " " << (*s)->tag()->category() << endl;
            seen_categories.insert((*s)->tag()->category());

            /* We use a visitor to do extra displaying, so that we can display
             * more detailed information for whatever our tag type is. */
            TagDisplayer displayer;
            (*s)->tag()->accept(displayer);

            cout << endl;
        }

        cout << endl;
    }
}

int main(int argc, char * argv[])
{
    try
    {
        CommandLine::get_instance()->run(argc, argv,
                "example_dep_tag", "EXAMPLE_DEP_TAG_OPTIONS", "EXAMPLE_DEP_TAG_CMDLINE");

        /* We start with an Environment, respecting the user's '--environment' choice. */
        std::tr1::shared_ptr<Environment> env(EnvironmentFactory::get_instance()->create(
                    CommandLine::get_instance()->a_environment.argument()));

        SeenCategories seen_categories;

        /* First, tell us about the 'security' set: */
        display_set(env, SetName("security"), seen_categories);

        /* Then the 'world' set: */
        display_set(env, SetName("world"), seen_categories);

        /* Now display a summary of seen categories. */
        cout << "Seen categories:" << endl;
        for (SeenCategories::const_iterator s(seen_categories.begin()), s_end(seen_categories.end()) ;
                s != s_end ; ++s)
        {
            cout << "    " << *s << ":" << endl;

            /* Fetch the category. */
            std::tr1::shared_ptr<const DepTagCategory> category(DepTagCategoryFactory::get_instance()->create(*s));

            cout << left << setw(20) << "        Visible:" << " " << boolalpha << category->visible() << endl;
            cout << left << setw(20) << "        ID:" << " " << category->id() << endl;
            cout << left << setw(20) << "        Title:" << " " << category->title() << endl;
            cout << left << setw(20) << "        Pre text:" << " " << category->pre_text() << endl;
            cout << left << setw(20) << "        Post text:" << " " << category->post_text() << endl;

            cout << endl;
        }
    }
    catch (const Exception & e)
    {
        /* Paludis exceptions can provide a handy human-readable backtrace and
         * an explanation message. Where possible, these should be displayed. */
        cout << endl;
        cout << "Unhandled exception:" << endl
            << "  * " << e.backtrace("\n  * ")
            << e.message() << " (" << e.what() << ")" << endl;
        return EXIT_FAILURE;
    }
    catch (const std::exception & e)
    {
        cout << endl;
        cout << "Unhandled exception:" << endl
            << "  * " << e.what() << endl;
        return EXIT_FAILURE;
    }
    catch (...)
    {
        cout << endl;
        cout << "Unhandled exception:" << endl
            << "  * Unknown exception type. Ouch..." << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}




Generated on Mon Sep 21 10:36:07 2009 for paludis by  doxygen 1.5.4