[pacman-dev] little error when installing/upgrading the first package in a new database

Xavier shiningxc at gmail.com
Wed Jul 4 17:45:10 EDT 2007


There was an odd error when the first package installed in a database
had a scriptlet :
 LANG=C sudo src/pacman/pacman --conf pacman.conf -Ud
/var/cache/pacman/pkg/filesystem-0.8-3.pkg.tar.gz
loading package data... done.
(1/1) checking for file conflicts
[####################################################################################################]
100%
error: could not open file
/home/xav/dev/pacman/foo/var/lib/pacman/local//filesystem-0.8-3/depends:
No such file or directory----------------------------]   0%
(1/1) installing filesystem
[####################################################################################################]
100%

This doesn't happen with package that doesn't have a scriptlet, and it
doesn't happen either when there is at least one other package in the
database.
But it still happened after running the same pacman command several
times (ie upgrading the
single package in the database).
I finally found why.

in add.c, alpm_add_commit function :
366       _alpm_log(PM_LOG_DEBUG, _("removing old package first
(%s-%s)"), oldpkg->name, oldpkg->version);

That part will remove the filesystem package if it existed (in case of
an upgrade),
and will also remove the entry from the database (filesystem directory
in $dbpath/local)

473         } else if(strcmp(entryname, ".INSTALL") == 0) {
474           /* the install script goes inside the db */
475           snprintf(filename, PATH_MAX, "%s/%s-%s/install", db->path,
476                    newpkg->name, newpkg->version);

That extracts the scriptlet to $dbpath/local//filesystem-0.8-3/install .

then later, we have this :
778     /* Update the requiredby field by scanning the whole database
779      * looking for packages depending on the package to add */
780     _alpm_pkg_update_requiredby(newpkg);

and later, this :
821     _alpm_log(PM_LOG_DEBUG, _("updating database"));
822     _alpm_log(PM_LOG_DEBUG, _("adding database entry '%s'"), newpkg->name);

So when update_requiredby is called, the entry hasn't been totally
written in the database, we only have the install file, but no depends
or desc file.

and some code from update_requiredby in package.c :
 756   pmdb_t *localdb = alpm_option_get_localdb();
 757   for(i = _alpm_db_get_pkgcache(localdb); i; i = i->next) {
...
 764     for(j = alpm_pkg_get_depends(cachepkg); j; j = j->next) {

So _alpm_get_pkgcache will return the filesystem package, because the
directory exists
in $dbpath/local/ , but alpm_pkg_get_depends will try to read the
depends file which doesn't exist yet, resulting in the error message.

Finding this didn't take too long, but this error should then appear
in every cases, as long as the package has a scriptlet.
But it didn't, as soon as there were more than one package in the db,
the error disappeared.
That's because of the pkg cache.
in package.c , _alpm_db_get_pkgcache function, we have :
106   if(!db->pkgcache) {
107     _alpm_db_load_pkgcache(db);
108   }

so the package database is loaded again only if db->pkgcache is NULL.
The first time we install filesystem, pkgcache will be NULL when that
function is called,
so it'll read the database, finding the partial filesystem entry.
And when we upgrade filesystem, it removes the old filesystem package
first and at this moment _alpm_db_remove_pkgfromcache function from
cache.c will be called, doing this :
152   _alpm_log(PM_LOG_DEBUG, _("removing entry '%s' from '%s' cache"),
153             alpm_pkg_get_name(pkg), db->treename);
154
155   db->pkgcache = alpm_list_remove(db->pkgcache, pkg, _alpm_pkg_cmp, &vdata);

which will result in a NULL db->pkgcache too.
There is no differences between an uninitialized list and an empty
list, unfortunately ...

When there is another package in the database, pkgcache won't be NULL
after the current package being upgraded is removed from pkgcache
list.
So the pkgcache won't be updated by reading the database again when
update_requiredby is called, and so it won't fail on a broken partial
filesystem entry, because it has been removed from pkgcache ealier.

While that issue was totally harmless, and never happens, because
there is always more than one package in the db, it was annoying to
get it every time when debugging, without knowing where it came from.
For fixing it, it shouldn't be too hard, but I'm not sure yet. Maybe
we can delay the extraction of the scriptlet to $dbpath/ , and only
installs it in the same time than the dabase entry is created.
Or maybe we can just call requiredby after the database entry is fully
created, I'm not sure..
Or maybe we can make the difference between an empty pkgcache and a
not initialized one.




More information about the pacman-dev mailing list