libdpkg: Add new package name accessors
authorGuillem Jover <guillem@debian.org>
Tue, 1 Mar 2011 02:55:54 +0000 (03:55 +0100)
committerGuillem Jover <guillem@debian.org>
Mon, 9 Jan 2012 07:33:39 +0000 (08:33 +0100)
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>
lib/dpkg/dpkg-db.h
lib/dpkg/libdpkg.map
lib/dpkg/pkg-show.c
lib/dpkg/pkg.c

index ba8fbd9..a22cac6 100644 (file)
@@ -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*,
index 9f80069..0bdc9f3 100644 (file)
@@ -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;
index a8a3b81..d9c4778 100644 (file)
 #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)
 {
index f554653..51a2ee8 100644 (file)
@@ -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;