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

libdpkg: Add new package name accessors

Those functions are meant to be used everywhere where we want to print
out a distinguishing package name instead of the currently ambiguous
pkg->set->name.

Based-on-patch-by: Raphaël Hertzog <hertzog@debian.org>
Patch-sponsored-by: Linaro Limited

Signed-off-by: Guillem Jover <guillem@debian.org>
Guillem Jover лет назад: 15
Родитель
Сommit
f790c4c763
4 измененных файлов с 126 добавлено и 0 удалено
  1. 21 0
      lib/dpkg/dpkg-db.h
  2. 3 0
      lib/dpkg/libdpkg.map
  3. 101 0
      lib/dpkg/pkg-show.c
  4. 1 0
      lib/dpkg/pkg.c

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

@@ -118,6 +118,9 @@ struct pkgbin {
     multiarch_foreign,
   } multiarch;
   const struct dpkg_arch *arch;
+  /* The following is the "pkgname:archqual" cached string, if this was a
+   * C++ class this member would be mutable. */
+  const char *pkgname_archqual;
   const char *description;
   const char *maintainer;
   const char *source;
@@ -329,6 +332,24 @@ int parseversion(struct versionrevision *rversion, const char *,
 const char *versiondescribe(const struct versionrevision*,
                             enum versiondisplayepochwhen);
 
+enum pkg_name_arch_when {
+  /* Never display arch. */
+  pnaw_never,
+  /* Display arch only when it's non-ambiguous. */
+  pnaw_nonambig,
+  /* Display arch only when it's a foreign one. */
+  pnaw_foreign,
+  /* Always display arch. */
+  pnaw_always,
+};
+
+void varbuf_add_pkgbin_name(struct varbuf *vb, const struct pkginfo *pkg,
+                            const struct pkgbin *pkgbin,
+                            enum pkg_name_arch_when pnaw);
+const char *pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin,
+                        enum pkg_name_arch_when pnaw);
+const char *pkg_name(struct pkginfo *pkg, enum pkg_name_arch_when pnaw);
+
 /*** from dump.c ***/
 
 void writerecord(FILE*, const char*,

+ 3 - 0
lib/dpkg/libdpkg.map

@@ -203,6 +203,9 @@ LIBDPKG_PRIVATE {
 	pkg_is_informative;
 	copy_dependency_links;
 	pkg_sorter_by_name;
+	varbuf_add_pkgbin_name;
+	pkgbin_name;
+	pkg_name;
 	pkg_summary;
 	pkg_abbrev_want;
 	pkg_abbrev_status;

+ 101 - 0
lib/dpkg/pkg-show.c

@@ -29,6 +29,107 @@
 #include <dpkg/dpkg-db.h>
 #include <dpkg/pkg-show.h>
 
+static bool
+pkgbin_name_needs_arch(const struct pkgbin *pkgbin,
+                       enum pkg_name_arch_when pnaw)
+{
+	switch (pnaw) {
+	case pnaw_never:
+		break;
+	case pnaw_foreign:
+		if (pkgbin->arch->type == arch_native ||
+		    pkgbin->arch->type == arch_all ||
+		    pkgbin->arch->type == arch_none)
+			break;
+		return true;
+	case pnaw_nonambig:
+		if (pkgbin->multiarch != multiarch_same)
+			break;
+	/* Fall through. */
+	case pnaw_always:
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * Add a string representation of the package name to a varbuf.
+ *
+ * Works exactly like pkgbin_name() but acts on the varbuf instead of
+ * returning a string. It NUL terminates the varbuf.
+ *
+ * @param vb      The varbuf struct to modify.
+ * @param pkg     The package to consider.
+ * @param pkgbin  The binary package instance to consider.
+ * @param pnaw    When to display the architecture qualifier.
+ */
+void
+varbuf_add_pkgbin_name(struct varbuf *vb,
+                       const struct pkginfo *pkg, const struct pkgbin *pkgbin,
+                       enum pkg_name_arch_when pnaw)
+{
+	varbuf_add_str(vb, pkg->set->name);
+	if (pkgbin_name_needs_arch(pkgbin, pnaw))
+		varbuf_add_archqual(vb, pkgbin->arch);
+	varbuf_end_str(vb);
+}
+
+/**
+ * Return a string representation of the package name.
+ *
+ * The returned string must not be freed, and it's permanently allocated so
+ * can be used as long as the non-freeing memory pool has not been freed.
+ *
+ * The pnaw parameter should be one of pnaw_never (never print arch),
+ * pnaw_foreign (print arch for foreign packages only), pnaw_nonambig (print
+ * arch for non ambiguous cases) or pnaw_always (always print arch),
+ *
+ * @param pkg     The package to consider.
+ * @param pkgbin  The binary package instance to consider.
+ * @param pnaw    When to display the architecture qualifier.
+ *
+ * @return The string representation.
+ */
+const char *
+pkgbin_name(struct pkginfo *pkg, struct pkgbin *pkgbin,
+            enum pkg_name_arch_when pnaw)
+{
+	if (!pkgbin_name_needs_arch(pkgbin, pnaw))
+		return pkg->set->name;
+
+	/* Cache the package name representation, for later reuse. */
+	if (pkgbin->pkgname_archqual == NULL) {
+		struct varbuf vb = VARBUF_INIT;
+
+		varbuf_add_str(&vb, pkg->set->name);
+		varbuf_add_archqual(&vb, pkgbin->arch);
+		varbuf_end_str(&vb);
+
+		pkgbin->pkgname_archqual = nfstrsave(vb.buf);
+
+		varbuf_destroy(&vb);
+	}
+
+	return pkgbin->pkgname_archqual;
+}
+
+/**
+ * Return a string representation of the package name.
+ *
+ * This is equivalent to pkgbin_name() but just for its installed pkgbin.
+ *
+ * @param pkg   The package to consider.
+ * @param pnaw  When to display the architecture qualifier.
+ *
+ * @return The string representation.
+ */
+const char *
+pkg_name(struct pkginfo *pkg, enum pkg_name_arch_when pnaw)
+{
+	return pkgbin_name(pkg, &pkg->installed, pnaw);
+}
+
 const char *
 pkg_summary(const struct pkginfo *pkg, int *len_ret)
 {

+ 1 - 0
lib/dpkg/pkg.c

@@ -33,6 +33,7 @@ pkgbin_blank(struct pkgbin *pkgbin)
 	pkgbin->essential = false;
 	pkgbin->multiarch = multiarch_no;
 	pkgbin->depends = NULL;
+	pkgbin->pkgname_archqual = NULL;
 	pkgbin->description = NULL;
 	pkgbin->maintainer = NULL;
 	pkgbin->source = NULL;