Libzypp/Application Layer/API Proposal

From openSUSE


Please, do not edit this page (yet)


Contents

About

This API has been designed by Katarína Machálková AKA Bubli to unify the high-level application access to the libzypp library.

Motto: We should use a stable and proven framework, supporting agile development and focusing on integrated testing

Common structure

Please, keep in mind that this is not a real code, just some human-readable sketch of the structure.

  • Define selectable types
   enum Type {
       PACKAGE,
       PATTERN,
       PATCH,
       LANGUAGE
   }
  • Selectable represented as a map (doesn't necessarily have to be STL map), just to make querying properties more obvious in this text
   Package = $[ 
   	name: MozillaFirefox 
   	summary: MozillaFirefox web browser 
   	size: 20.5M
   	installedVersion: [ 2.0.0, ... ]
   	availableVersion: [ 2.0.1, ... ]
   	description : " .. " 
   	relatedTo: X Window System (pattern) //maybe?
   	repository: http://example.com/pub/suse/10.3
   ]
  • Specify universal query over selectables
   Query q = new Query( ); //create query object
  • Define type of selectables which will be subjected to query
   q->addType(PACKAGE);
  • Specify selectable attributes (keys and corresponding values) and refine the query
   q->addAttribute( key, value ); // e.g. ("name", "blurb" )
   //this means: select * from packages where name="blurb"
  • Create pool iterator (based on the above query as a parameter)
   Pool pool = new Pool (q); 
  • Process created pool (in UI)
   struct do_something { // this is a function object, might or might not be provided by UI
       ...
       operator() (Selectable *) { ... }
       ...
   }
   
   for_each(pool->begin(), pool->end(), do_something); 


Higher Level Objects: Patterns, Patches, Languages

The following section describes how to define a query. Creating the pool remains the same as above

Parameter Description Proposed API
Show all patterns For each pattern, show its status, name, description, icon,...

Provide also its category, so patterns can be arranged into groups

Query q = new Query;
q->addType( PATTERN ); //select * from Patterns
Show all patches For each patch, show its status, summary, category, version, size,...
Query q = new Query;
q->addType( PATCH ); //select * from Patches
Show all languages For each language, show its status, code, name,...
Query q = new Query;
q->addType( LANGUAGE ); //select * from Languages
Show all repositories For each repository, show its name and URL
//NOP, already implemented
zypp::ResPoolProxy::repository_iterator
Show all RPM Groups Show all RPM groups in a tree structure
//NOP, implemented in YRpmGroupTree (in libyui)


Filter views and queries

The following section describes how to define a query. Creating the pool remains the same as above

Action Description Proposed API
Filter packages by status
(select * from Packages where Status = S_*)
For given status, select and show only packages with this state. For combination of states (e.g. show all installed OR updated), use bitwise OR of states
enum Status {
    S_Install 0 
    S_Autoinstall 1
    S_Keep 1 << 2
    S_Delete 1 << 3 ...
}
   
Query q = new Query;
q->addType( PACKAGE );
q=>addAttribute("status", S_Install | S_Autoinstall | S_Update | S_AutoUpdate);
Filter packages by their relation to Pattern For given pattern, select and show only related packages (referred to as patternContent today). For simplicity sake, these are the packages with Requires, Suggests and Recommends flag for this pattern.
Query q0 = new Query;
q0->addType( PATTERN );
q0->addAtrribute("name", "YaST Development);

//Select * from Packages where $name IN 
//(select Requires, Suggests, Recommends from 
//Patterns where $name="YaST dev.")
Query q = new Query;
q->addType( PACKAGE );
q->addAttribute("relatedTo", q0);
//maybe use direct pointer to a pattern as a second parameter?
Filter packages by their relation to Language For given languages, select and show only 'related' packages. These are the packages that 'freshen' this language (zypp::Dep::FRESHEN)
Query q0 = new Query;
q0->addType( LANGUAGE );
q0->addAtrribute("name", "Afrikaans");

//Select * from Packages where $name IN 
//(select Freshen_packages from 
//Languages where $name="Afrikaans")
Query q = new Query;
q->addType( PACKAGE );
q->addAttribute("relatedTo", q0);
Filter packages by their relation to Patch For given patch, select and show only 'related' packages. These are the packages that will be updated if this patch gets installed
Query q0 = new Query;
q0->addType( PATCH );
q0->addAtrribute("name", "libzypp-12345");

//Select * from Packages where $name IN 
//(select Update_packages from 
//Patch where $name="libzypp-12345")
Query q = new Query;
q->addType( PACKAGE );
q->addAttribute("relatedTo", q0);
Filter packages by RPM group For given RPM group, select and show all packages it contains.
Query q = new Query;
q->addType( PACKAGE );
q->addAttribute("group", "Games/Board/kde3-games");
Filter packages by their presence on certain repository For given repository, show all packages which are available on this repository
Query q = new Query( PACKAGE ); 
q->addAttribute("repository", "openSUSE10.3 - retail");
//2nd parameter may not necessarily be a string, but it must be
//something that uniquely identifies this repository
Filter packages by
  • name
  • summary
  • description
  • RPM_provides
  • RPM_requires
  • something else, all of the above,...
Select and show those packages whose name (summary, description,...) matches search string. Specify also the type of the match (exact, regexp, begins_with
enum SearchMode {
    Exact,
    Regexp,
    Begins_with, ...
}

Query q = new Query( PACKAGE ); 
q->addAttribute("name", "blurb");
q->addAttribute("summary", "blurb");
q->setSearchMode( Regexp )
Filter patches by category For given patch category, select and show all patches within this category
enum Category {
    Installable,
    InstallableAndInstalled,
    PackageManagement,...
}

Query q = new Query ( PATCH );
q->addAttribute("category", Installable);


Solver interface

Action Description Proposed API
Show packages modified by solver Select and show all packages whose status has been modified by solver (in fact, 'Except for manual selection, these packages will be installed to satisfy dependencies')
Query q = new Query( PACKAGE ); 
q->addAttribute("modifiedBy", SOLVER);


Export/Import multiple selectables

Operation Proposed API
Export list of all pkgs and patterns into XML file
Export (char *filename)
{
    zypp::syscontent::Writer writer;
    const zypp::ResPool & pool = zypp::getZYpp()->pool();
       
    for_each( pool.begin(), pool.end(),
        boost::bind( &zypp::syscontent::Writer::addIf,
            boost::ref(writer),
            _1));
       
    try
    {
        //open file for writing and try to dump syscontent into it
        std::ofstream exportFile(  filename );
        exportFile.exceptions(std::ios_base::badbit | std::ios_base::failbit );
        exportFile << writer;
       
    }
   
    catch (std::exception & exception)
    {    
        //delete partially written file (don't care if it doesn't exist)
        (void) unlink( filename );
   
        return false;
    }
   
    return true;
}
   
string filename = UI::AskForFile( ... );

if (! Export (filename) )
{
    UI::OpenDialog ("Error msg");
}
Import list of all pkgs and patterns from XML file
Import (string filename)
{
    try {
        zypp::syscontent::Reader reader (importFile);
           
        //maps to store package/pattern data into
        map importPkgs;
        map importPatterns;
           
        //Import syscontent reader to a map $[ "package_name" : pointer_to_data]
        for (zypp::syscontent::Reader::const_iterator it = reader.begin();
            it != reader.end();
            it ++ )
        {
            string kind = it->kind();
            
            // importMapPair => std::pair
            if ( kind == "package" )
                importPkgs.insert( importMapPair( it->name(), *it ) );
            else if ( kind == "pattern" )
                importPatterns.insert( importMapPair( it->name(), *it ) );
        }
           
        //Change status of appropriate packages and patterns
        for_each ( PackagesBegin(), PackagesEnd(),
            //isWanted => package name found in importPkgs map
        //this changes Selectable status depending on its presence
        //in the import map
            importSelectable ( package, isWanted ) );
   
        //The same thing with patterns
    }
    catch ( const zypp::Exception & exception )    
    {
        return false;
    }
    
    return true;
}
   
string filename = UI::AskForFile(...);
   
if (!Import)
{
    UI::OpenDialog("error msg");
}