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

Bug#92263: patch for bug 92263, dpkg --list truncating package names

tags 92263 + patch

This has annoyed me for a long time, so in a fit of frustration I decided
to do something about it.  Reading over the bug history, I thought I'd
correct some misstatements that I saw:

- it's spelled COLUMNS, not COLUMN, and it must be an environment variable,
  not a shell variable (so export it, bash users)
- dpkg simply execvp's dpkg-query when handling --list, so using the second
  instead of the first won't help
- yes, there's a built in default of 80, because that's the standard
  screen width


This patch robs from Peter to pay Paul:  if the 'name' column width is
shorter than the longest package name to be displayed, 'name' is increased
just as much as needed, and 'description' is decreased by the same amount.
If this bothers you, you're probably already using --show or COLUMNS.

Tracking the longest package name obviously makes this a two-pass routine
instead of the existing print-as-you-go.  During the first pass, we keep
the longest name length, and remember the 'pkgl' indices of the entries
to print in a separate list.  The printing pass only traverses the shorter
separate list, not the entire list a second time.

Doing an expandable list of integers is done either with glib or a kludged
version using the same identifiers.  Choose yer poison.

Caveats:  it only takes effect in the case where you are listing specific
packages (or package patterns), not the general case where you list all
installed packages.  Also, it doesn't try to adjust the 'version' column,
because that's too big of a change for a dabbler to make.

Created against version 1.10.21.  Apply this to main/query.c and the
resulting dpkg-query can be put somewhere in your PATH before /usr/bin
to take effect.  I don't expect it to go into the real dpkg-query.

If you use the glib version, also change ../Makefile.conf.in:
add `pkg-config --cflags glib-2.0` and `pkg-config --libs glib-2.0` to
INCLUDE_CFLAGS and LIBS, respectively.

--- query.c-1.10.21.orig	2004-04-24 18:18:29.000000000 -0400
+++ query.c-widename	2004-05-10 08:01:48.000000000 -0400
@@ -43,6 +43,39 @@
 #include "filesdb.h"
 #include "main.h"
+#if 1
+#include <glib.h>
+/* If you don't have the libglib2.0-dev package installed, flip 1 to 0 and
+   use this crappy version, written by a snail outside my window.  It mallocs
+   tiny blocks extremely often, so is slow.  */
+typedef struct GSList
+    int  data;
+    struct GSList *next;
+} GSList;
+static struct GSList* g_slist_append (struct GSList *start, int n)
+    struct GSList *i, *e;
+    e = (struct GSList*)malloc(sizeof(struct GSList));
+    e->data = n;
+    e->next = NULL;
+    if (!start)
+      return e;
+    i = start;
+    while (i->next) i = i->next;
+    i->next = e;
+    return start;
+#define GINT_TO_POINTER(x)  x
+#define GPOINTER_TO_INT(x)   x
 static const char* showformat		= "${Package}\t${Version}\n";
@@ -120,7 +153,7 @@
   return ws.ws_col;
-static void list1package(struct pkginfo *pkg, int *head) {
+static void list1package(struct pkginfo *pkg, int *head, int longest_name) {
   int l,w;
   static int nw,vw,dw;
   const char *pdesc;
@@ -133,6 +166,11 @@
     nw=(14+w);		/* name width */
     vw=(14+w);		/* version width */
     dw=(44+(2*w));	/* description width */
+    l = longest_name - nw;
+    if (l > 0) {
+      nw += l;
+      dw -= l;
+    }
     sprintf(format,"%%c%%c%%c %%-%d.%ds %%-%d.%ds %%.*s\n", nw, nw, vw, vw);
@@ -165,7 +203,8 @@
   struct pkginfo *pkg;
   struct pkginfo **pkgl;
   const char *thisarg;
-  int np, i, head, found;
+  int np, i, head, found, maxname;
+  GSList *pkgs, *pkgsiter;
@@ -186,21 +225,29 @@
     for (i=0; i<np; i++) {
       pkg= pkgl[i];
       if (pkg->status == stat_notinstalled) continue;
-      list1package(pkg,&head);
+      list1package(pkg,&head,maxname);
   } else {
+    maxname= 0;
+    pkgs= NULL;
     while ((thisarg= *argv++)) {
       found= 0;
       for (i=0; i<np; i++) {
         pkg= pkgl[i];
         if (fnmatch(thisarg,pkg->name,0)) continue;
-        list1package(pkg,&head); found++;
+        if (strlen(pkg->name) > maxname) maxname = strlen(pkg->name);
+        pkgs= g_slist_append(pkgs,GINT_TO_POINTER(i));
+        found++;
       if (!found) {
         fprintf(stderr,_("No packages found matching %s.\n"),thisarg);
-	nerrs++;
+        nerrs++;
+    for (pkgsiter= pkgs; pkgsiter; pkgsiter = pkgsiter->next)
+      list1package(pkgl[GPOINTER_TO_INT(pkgsiter->data)],&head,maxname);
+    /* No point in deallocating pkgs; the process will be exiting in
+       about 200 milliseconds, and the system will get it all back then. */
   if (ferror(stdout)) werr("stdout");
   if (ferror(stderr)) werr("stderr");  

Reply to: