Просмотр исходного кода

libdpkg: Add installed package instance tracking support

Guillem Jover лет назад: 14
Родитель
Сommit
31a7dee81b
4 измененных файлов с 107 добавлено и 0 удалено
  1. 3 0
      lib/dpkg/dpkg-db.h
  2. 1 0
      lib/dpkg/libdpkg.map
  3. 24 0
      lib/dpkg/pkg.c
  4. 79 0
      lib/dpkg/test/t-pkginfo.c

+ 3 - 0
lib/dpkg/dpkg-db.h

@@ -226,6 +226,7 @@ struct pkgset {
     struct deppossi *available;
     struct deppossi *installed;
   } depended;
+  int installed_instances;
 };
 
 /*** from dbdir.c ***/
@@ -267,6 +268,8 @@ void modstatdb_shutdown(void);
 /*** from database.c ***/
 
 void pkgset_blank(struct pkgset *set);
+int pkgset_installed_instances(struct pkgset *set);
+
 void pkg_blank(struct pkginfo *pp);
 void pkgbin_blank(struct pkgbin *pifp);
 bool pkg_is_informative(struct pkginfo *pkg, struct pkgbin *info);

+ 1 - 0
lib/dpkg/libdpkg.map

@@ -197,6 +197,7 @@ LIBDPKG_PRIVATE {
 	dpkg_arch_save_list;
 
 	# Package struct handling
+	pkgset_installed_instances;
 	pkg_blank;
 	pkgbin_blank;
 	pkg_name_is_illegal;

+ 24 - 0
lib/dpkg/pkg.c

@@ -22,6 +22,7 @@
 #include <config.h>
 #include <compat.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include <dpkg/dpkg-db.h>
@@ -33,6 +34,15 @@
 void
 pkg_set_status(struct pkginfo *pkg, enum pkgstatus status)
 {
+	if (pkg->status == status)
+		return;
+	else if (pkg->status == stat_notinstalled)
+		pkg->set->installed_instances++;
+	else if (status == stat_notinstalled)
+		pkg->set->installed_instances--;
+
+	assert(pkg->set->installed_instances >= 0);
+
 	pkg->status = status;
 }
 
@@ -132,6 +142,7 @@ pkgset_blank(struct pkgset *set)
 	set->depended.available = NULL;
 	set->depended.installed = NULL;
 	pkg_blank(&set->pkg);
+	set->installed_instances = 0;
 	set->pkg.set = set;
 	set->pkg.arch_next = NULL;
 }
@@ -150,6 +161,19 @@ pkgset_link_pkg(struct pkgset *set, struct pkginfo *pkg)
 	set->pkg.arch_next = pkg;
 }
 
+/**
+ * Get the number of installed package instances in a package set.
+ *
+ * @param set The package set to use.
+ *
+ * @return The count of installed packages.
+ */
+int
+pkgset_installed_instances(struct pkgset *set)
+{
+	return set->installed_instances;
+}
+
 static int
 nes(const char *s)
 {

+ 79 - 0
lib/dpkg/test/t-pkginfo.c

@@ -43,10 +43,89 @@ test_pkginfo_informative(void)
 	/* FIXME: Complete. */
 }
 
+static void
+test_pkginfo_instance_tracking(void)
+{
+	struct pkgset set;
+	struct pkginfo pkg2, pkg3, pkg4;
+
+	pkgset_blank(&set);
+	pkg_blank(&pkg2);
+	pkg_blank(&pkg3);
+	pkg_blank(&pkg4);
+
+	test_pass(pkgset_installed_instances(&set) == 0);
+
+	/* Link the other instances into the pkgset. */
+	pkgset_link_pkg(&set, &pkg4);
+	pkgset_link_pkg(&set, &pkg3);
+	pkgset_link_pkg(&set, &pkg2);
+
+	/* Test installation state transitions. */
+	pkg_set_status(&pkg4, stat_installed);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_installed);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_triggerspending);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_triggersawaited);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_halfconfigured);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_unpacked);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_halfinstalled);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_configfiles);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 0);
+
+	pkg_set_status(&pkg4, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 0);
+
+	/* Toggle installation states on various packages. */
+	pkg_set_status(&pkg4, stat_installed);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg2, stat_halfinstalled);
+	test_pass(pkgset_installed_instances(&set) == 2);
+
+	pkg_set_status(&set.pkg, stat_configfiles);
+	test_pass(pkgset_installed_instances(&set) == 3);
+
+	pkg_set_status(&pkg3, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 3);
+
+	pkg_set_status(&pkg3, stat_unpacked);
+	test_pass(pkgset_installed_instances(&set) == 4);
+
+	pkg_set_status(&set.pkg, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 3);
+
+	pkg_set_status(&pkg2, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 2);
+
+	pkg_set_status(&pkg3, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 1);
+
+	pkg_set_status(&pkg4, stat_notinstalled);
+	test_pass(pkgset_installed_instances(&set) == 0);
+}
+
 static void
 test(void)
 {
 	test_pkginfo_informative();
+	test_pkginfo_instance_tracking();
 
 	/* FIXME: Complete. */
 }