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

Re: Greetings



On Fri, 19 Mar 1999, Kirk Saranathan wrote:

> Hello, Jason.  My name is Kirk Saranathan and I'm one of the engineers
> at Corel working on the Corel Linux distribution.  I was given your
> contact info by Wichert Akkerman.  I'm hoping to get some info from you
> about the internals of apt so that I may modify (or create) a package
> management front-end to use apt.  I'm currently reading the source on
> the apt package and am still learning.  I read about a gnome frontend to
> apt but haven't been able to find anything thus far (except for kpackage
> which uses dpkg directly).  Could you point me in the right direction?

I belive that Havoc has already told you some info on where to find
compiled gnome-apt binarys, all the apt sources are in CVS, the path for
it is

:pserver:anonymous@cvs.debian.org:/cvs/deity

modules apt and gnome-apt. Some time back I posted a few long summaries on
how to use the library, but formal documentation is scarse :>

The best is often just to ask questions on IRC but you doing this for a
day job in ontario may make that impossible

Hmm, I can't find the summary in the list archives.. here are some
snipits:

-----------
The library source and such forth is in CVS as usual. There is a new
forked development tree called 'apt' which is distinct and very different
from the current release. To get it do something like

export CVSROOT=":pserver:anonymous@cvs.debian.org:/cvs/deity"
cvs login
cvs co apt
cd apt
make startup
make

You'll need g++ and libstdc++2.9. To make use of the library from your
program you'll want to include -L .../apt/build/lib and -I 
.../apt/build/include and use -lapt-pkg

Then you can start working on removing your library and replacing it with
this one.. I guess the main areas of questioning would be something like

  1) How do I startup the library
  2) How do I get a list of packages
     - Packages that a package depends on
     - With some sort of filter criteria
  3) How do I install/remove/keep a package

I guess I'll write another mail outlining the basic elements of each of
these.
----------

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.

  - 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.
  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.
  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.



Reply to: