[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: gdselect alpha 3 [libapt]



1) How do I startup the library
 This is much longer than I would like it to be, but can't be simplified
 without loosing something :< The sequence can be divided into 3 stages,
    - Configuration
    - Cache load+parse
    - Dependency correction (optional)
 Omitting error checking this sequence looks like:
    // Configuration phase, read config file and sourcelist
    pkgInitialize(*_config);
    OpTextProgress Progress(*_config); 
    pkgSourceList List; 
    List.ReadMainList();

    // Parse (if necessary) the package files
    pkgMakeStatusCache(List,Progress);
    Progress.Done();

    // Open and associate the cache file
    FileFd *File = new FileFd(_config->FindDir("Dir::Cache::pkgcache"),
                              FileFd::ReadOnly);
    MMap *Map = new MMap(*File,MMap::Public | MMap::ReadOnly);
    pkgDepCache *Cache = new pkgDepCache(*Map,Progress); 
    Progress.Done();

 A complete example of this can be found int cmdline/apt-get.cc inside the
 CacheFile::Open function. Error checking makes it considerably larger.

 You can create your own Progress class to interface with a GTK progress
 meter, an example of this is in gui/progress.cc.

2) How do I get a list of packages
   - Packages that a package depends on
   - With some sort of filter criteria

 Package lists of all sorts are derived by iterating over the cache with
 a Package Iterator. There are many examples of this in cmbline/apt-get.cc
 functions Show*. An example:

   // Print the name of every package
   pkgCache::PkgIterator I = Cache.PkgBegin();
   for (; I.end() == false; I++)
     cout << I.Name() << endl;

 In the usual configuration there are a pair of main datastructures, the
 'Cache' which contains static information derived from the pacage lists 
  and the 'DepCache' which contains runtime generated information such as
  dependency state values, selected versions, the install/remove flag,
  etc. The iterators only iterate over the 'Cache' but you can access the
  associated DepCache record for an Iterator with something like:

  cout << "Version " << Cache[I].CurVersion << " is installed." << endl;
  cout << "Version " << Cache[I].CandVersion << " is available for install." << endl;

  The DepCache contains test members to determine if a package has broken
  deps, if it is being upgraded, and other things like that [see the
  header]

  Varios other specialized classes have their own Extension Structures
  which allow them to associate some data with static records from the
  cache.

  Dependencies are directed through the version list for each package and
  to get at them you need to decide on a version that you want to see the
  Dependencies for. [Read section 3 to make some sense of this]. Typically
  GUI's display the Candidate Version's Dependency list which would be
  achived like:
 
  pkgCache::DepIterator Dep = Cache[I].CandiateVerIter(Cache);
  for (; Dep.end() == false; Dep++)
    <something>
  
 - Remeber to verify *VerIter is not at 'end', this single problem
   has caused the majority of APT crashes.

3) How do I install/remove/keep a package
  The DepCache keeps track of two versions for every package and an
  indicator of what version is selected in the target state.
  
  The two versions are called the InstallVersion and the CandidateVersion.
  It is critical to understand their meaning and roles. InstallVersion is 
  the version of the package that is installed in the system, it never
  changes. The CandidateVersion is selected from the version set and
  represents the newest version of the package. A package can either 
  select the Null version, the InstallVersion or the CandidateVersion as
  it's desired desintation.

  That said, installing a package is simple. If you have an iterator
  for the package,

  Cache.MarkInstall(i,true|false);

  The parameter indicates if AutoInstalling is desired. If true the
  library will make a trivial attempt to correct any -direct- problems
  caused by installing the package. Typically this means it installs the
  dependents. The functions MarkRemove (deinstall) and MarkKeep (restore
  to original state) are also available.

  The Mark* functions also compute the side effects of the change
  throughout the dependency network. It takes into account ALL possible
  effects of this change which includes indirection through a virtual
  package, 'or' dependency groups and others.

Recomended Implementation
 The best way to make use of the library in a GUI is with an owner draw
 tree widget. In most GUI implementations this means you pass an object
 handle and a draw function to the tree. To get the best use out of the
 library you would pass the package pointer to the tree and a draw
 function that gets it's information directly from the cache. This does
 two things,
   1) Assures minimal memory usage by not duplicating strings
   2) Assures the tree is always perfectly in sync with the state of the
      package in the fastest manner possible

Other Things
 There is a set of classes aimed at accessing information directly from
 the index files, I can explain them in a future email
 
 APT has a built in error handling mechanism. Errors of various sorts can
 trickle up in something called the Global Error Object (_error) It
 maintains a list textual problem descriptions, when many functions
 fail they will put their reason into the _error class and return false.
 Errors can be printed to the console with _error->DumpErrors(). You will
 want to make a function that takes the error text and puts it into a
 dialog, see gui/errorshow.cc.

 There is also a built in configuration and command-line handling
 mechanism represented by the Configuration class. A global instance
 for global configuration is called _config. It stored directory things 
 and others in a heigharchical key/value database. The command line parser
 takes command line arguments and sets the proper database entry allowing
 a uniform and simple configuration mechanism. 

 Very soon the new tree will have the completed acquire system which will
 allow you to write a pretty front end to the download progress meter,
 that's not finished yet though.

 The document build/doc/cache.text describes in detail each and every
 bit of data that can be directly acessed via the cache. There is a tad
 of a discontinuity here though,

   pkgCache::PkgIterator I;
   I.Name();           // Gives a const char * for the name
   I->Name;            // Gives an untranslated unsinged long
   
   I.VersionList();    // Gives a Version Iterator 
   I->VersionList;     // Gives an untranslated unsigned long

 Some things such as the priority feild must be accessed with -> while
 others only provide sensible results if used with the function call form.

Jason


Reply to: