]> err.no Git - dpkg/commitdiff
Add support for configurable package listings (not complete yet)
authorWichert Akkerman <wakkerma@debian.org>
Tue, 24 Jul 2001 17:08:43 +0000 (17:08 +0000)
committerWichert Akkerman <wakkerma@debian.org>
Tue, 24 Jul 2001 17:08:43 +0000 (17:08 +0000)
ChangeLog
debian/changelog
main/main.h
main/query.c
main/query.h [new file with mode: 0644]
main/showpkg.c [new file with mode: 0644]

index eb64c31973679eb0fbb0fbe42f2ce00122727a6c..72a851fd988602783d5e2dad762b409d3b51a67a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Jul 24 19:07:43 CEST 2001 Wichert Akkerman <wakkerma@debian.org>
+
+  * main/showpkg.c, main/query.h: new files
+  * main/query.c: add support for show options
+
 Wed Jul 18 17:28:38 CEST 2001 Wichert Akkerman <wakkerma@debian.org>
 
   * main/Makefile.in, debian/rules: install dpkg-query as well
index a3841b2cd5bccc6df960b26f6c4a62bd652ec3d3..40b48cdda8d02bef0915074d0f9f12d076da54cd 100644 (file)
@@ -29,6 +29,9 @@ dpkg (1.10) unstable; urgency=low
   * dselect now accepts regular expressions when searching for packages
     and can search in package descriptions as well.
     Closes: Bug#81009,#83139
+  * Move query commands into a seperate dpkg-query command. For the old options
+    (-L,-l,-s,-S) dpkg will still call it for you.
+  * Add configurable package listing support to dpkg-query
 
  -- Wichert Akkerman <wakkerma@debian.org>  Tue, 17 Jul 2001 22:05:38 +0200
 
index ac255d77fd40228f6fd847898bf4f625593335aa..c0515be247e4c6b7ed9e1a9ce4e355f7d6fe9797 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * dpkg - main program for package management
- * dpkg-deb.h - external definitions for this program
+ * main.h - external definitions for this program
  *
  * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
  *
index a0d4a62a27d9cab46eddce68faa4a6a2e0db1778..f467dabf51dbfaa66f6efa03866da0cbdf083f65 100644 (file)
@@ -3,6 +3,7 @@
  * enquiry.c - status enquiry and listing options
  *
  * Copyright (C) 1995,1996 Ian Jackson <ijackson@gnu.ai.mit.edu>
+ * Copyright (C) 200,2001 Wichert Akkerman <wakkerma@debian.org>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
 
 #include "filesdb.h"
 #include "main.h"
+#include "query.h"
+
+static const char* showformat          = "${pkg:Package}\t${pkg:Version}\n";
+
 
 void ensure_package_clientdata(struct pkginfo *pkg) {
   if (pkg->clientdata) return;
@@ -153,7 +158,7 @@ Desired=Unknown/Install/Remove/Purge/Hold\n\
          pkg->name,
          versiondescribe(&pkg->installed.version,vdew_never),
          l, pdesc);
-}         
+}
 
 void listpackages(const char *const *argv) {
   struct pkgiterator *it;
@@ -369,8 +374,60 @@ void enqperpackage(const char *const *argv) {
   }
 }
 
+void showpackages(const char *const *argv) {
+  struct pkgiterator *it;
+  struct pkginfo *pkg;
+  struct pkginfo **pkgl;
+  const char *thisarg;
+  int np, i, found;
+  const struct lstitem* fmt = parseformat(showformat);
+
+  if (!fmt) {
+    nerrs++;
+    return;
+  }
+
+  modstatdb_init(admindir,msdbrw_readonly);
+
+  np= countpackages();
+  pkgl= m_malloc(sizeof(struct pkginfo*)*np);
+  it= iterpkgstart(); i=0;
+  while ((pkg= iterpkgnext(it))) {
+    assert(i<np);
+    pkgl[i++]= pkg;
+  }
+  iterpkgend(it);
+  assert(i==np);
+
+  qsort(pkgl,np,sizeof(struct pkginfo*),pkglistqsortcmp);
+  
+  if (!*argv) {
+    for (i=0; i<np; i++) {
+      pkg= pkgl[i];
+      if (pkg->status == stat_notinstalled) continue;
+      show1package(fmt,pkg);
+    }
+  } else {
+    while ((thisarg= *argv++)) {
+      found= 0;
+      for (i=0; i<np; i++) {
+        pkg= pkgl[i];
+        if (fnmatch(thisarg,pkg->name,0)) continue;
+        show1package(fmt,pkg); found++;
+      }
+      if (!found) {
+        fprintf(stderr,_("No packages found matching %s.\n"),thisarg);
+       nerrs++;
+      }
+    }
+  }
+  if (ferror(stdout)) werr("stdout");
+  if (ferror(stderr)) werr("stderr");  
+  freeformat(fmt);
+}
+
 static void printversion(void) {
-  if (fputs(_("Debian GNU/Linux `"), stdout) < 0) werr("stdout");
+  if (fputs(_("Debian"), stdout) < 0) werr("stdout");
   if (fputs(DPKG, stdout) < 0) werr("stdout");
   if (fputs(_("' package management program version "), stdout) < 0) werr("stdout");
 //  if (fputs( DPKG_VERSION_ARCH ".\n", stdout) < 0) werr("stdout");
@@ -390,12 +447,14 @@ Usage: \n\
   dpkg -p|--print-avail <package-name> ... display available version details\n\
   dpkg -L|--listfiles <package-name> ...   list files `owned' by package(s)\n\
   dpkg -l|--list [<pattern> ...]           list packages concisely\n\
+  dpkg -W|--show <pattern> ...             show information on package(s)\n\
   dpkg -S|--search <pattern> ...           find package(s) owning file(s)\n\
   dpkg --help | --version                  show this help / version number\n\
   dpkg --licence                           print copyright licensing terms\n\
 \n\
 Options:\n\
   --admindir=<directory>     Use <directory> instead of %s\n\
+  --showformat=<format>      Use alternative format for --show\n\
   -D|--debug=<octal>         Enable debugging - see -Dhelp or --debug=help\n"),
            ADMINDIR) < 0) werr ("stdout");
 }
@@ -446,18 +505,20 @@ static const struct cmdinfo cmdinfos[]= {
 #define OBSOLETE(longopt,shortopt) \
  { longopt, shortopt, 0,0,0, setobsolete, 0, 0, 0 }
 
-  ACTION( "listfiles",                      'L', act_listfiles,     enqperpackage   ),         //
-  ACTION( "status",                         's', act_status,               enqperpackage   ),  //
-  ACTION( "print-avail",                    'p', act_printavail,           enqperpackage   ),  //
-  ACTION( "list",                           'l', act_listpackages,         listpackages    ),  //
-  ACTION( "search",                         'S', act_searchfiles,          searchfiles     ),  //
-
-  { "admindir",           0,   1,  0, &admindir,       0                             },
-  { "help",              'h',  0,  0, 0,               helponly                      },
-  { "version",            0,   0,  0, 0,               versiononly                   },
-  { "licence",/* UK spelling */ 0,0,0,0,               showcopyright                 },
-  { "license",/* US spelling */ 0,0,0,0,               showcopyright                 },
-  {  0,                   0                                                          }
+  ACTION( "listfiles",                      'L', act_listfiles,     enqperpackage   ),
+  ACTION( "status",                         's', act_status,        enqperpackage   ),
+  ACTION( "print-avail",                    'p', act_printavail,    enqperpackage   ),
+  ACTION( "list",                           'l', act_listpackages,  listpackages    ),
+  ACTION( "search",                         'S', act_searchfiles,   searchfiles     ),
+  ACTION( "show",                           'W', act_listpackages,  showpackages    ),
+
+  { "admindir",           0,   1,  0, &admindir,       0                            },
+  { "showformat",         0,   1,  0, &showformat,     0                            },
+  { "help",              'h',  0,  0, 0,               helponly                     },
+  { "version",            0,   0,  0, 0,               versiononly                  },
+  { "licence",/* UK spelling */ 0,0,0,0,               showcopyright                },
+  { "license",/* US spelling */ 0,0,0,0,               showcopyright                },
+  {  0,                   0                                                         }
 };
 
 int main(int argc, const char *const *argv) {
diff --git a/main/query.h b/main/query.h
new file mode 100644 (file)
index 0000000..bdbc84b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * dpkg-query - program to query the package database
+ * query.h - external definitions for this program
+ *
+ * Copyright (C) 2001 Wichert Akkerman <wakkerma@debian.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef QUERY_H
+#define QUERY_H
+
+struct lstitem;
+
+/* from showpkg.c */
+struct lstitem* parseformat(const char* fmt);
+void freeformat(struct lstitem* head);
+void show1package(const struct lstitem* head, struct pkginfo *pkg);
+
+#endif
+
diff --git a/main/showpkg.c b/main/showpkg.c
new file mode 100644 (file)
index 0000000..eb116f4
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * dpkg-query - program to query the package database
+ * showpkg.c - customizable package listing
+ *
+ * Copyright (C) 2001 Wichert Akkerman <wakkerma@debian.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <config.h>
+#include <dpkg.h>
+#include <dpkg-db.h>
+
+#include <parsedump.h>
+#include "main.h"
+
+
+typedef enum { invalid, string, field } itemtype_t;
+
+struct lstitem {
+       itemtype_t type;
+       size_t width;
+       char* data;
+       struct lstitem* next;
+};
+
+
+static struct lstitem* alloclstitem() {
+       struct lstitem* buf;
+
+       buf=(struct lstitem*)malloc(sizeof(struct lstitem));
+       buf->type=invalid;
+       buf->next=NULL;
+       buf->data=NULL;
+       buf->width=0;
+
+       return buf;
+}
+
+static void parsefield(struct lstitem* cur, const char* fmt, const char* fmtend) {
+       int len;
+
+       len=fmtend-fmt+1;
+
+       cur->type=field;
+       cur->data=(char*)malloc(len+1);
+       memcpy(cur->data, fmt, len);
+       cur->data[len]='\0';
+}
+
+static void parsestring(struct lstitem* cur, const char* fmt, const char* fmtend) {
+       int len;
+       char* write;
+
+       len=fmtend-fmt+1;
+
+       cur->type=string;
+       write=cur->data=(char*)malloc(len+1);
+       while (fmt<fmtend) {
+               if (*fmt=='\\') {
+                       fmt++;
+                       switch (*fmt) {
+                               case 'n':
+                                       *write='\n';
+                                       break;
+                               case 't':
+                                       *write='\t';
+                                       break;
+                               case 'r':
+                                       *write='\r';
+                                       break;
+                               case '\\':
+                               default:
+                                       *write=*fmt;
+                                       break;
+                       }
+               } else
+                       *write=*fmt;
+               write++;
+               fmt++;
+       }
+       *write='\0';
+}
+
+
+void freeformat(struct lstitem* head) {
+       struct lstitem* next;
+
+       while (head) {
+               next=head->next;
+               free(head->data);
+               free(head);
+               head=next;
+       }
+}
+
+struct lstitem* parseformat(const char* fmt) {
+       struct lstitem* head;
+       struct lstitem* cur;
+       const char* fmtend;
+
+       head=cur=NULL;
+       
+       while (*fmt) {
+               if (cur)
+                       cur=cur->next=alloclstitem();
+               else
+                       head=cur=alloclstitem();
+
+               if (fmt[0]=='$' && fmt[1]=='{') {
+                       fmtend=strchr(fmt, '}');  // TODO: check for not-found
+                       if (!fmtend) {
+                               fprintf(stderr, _("Closing brace missing in format\n"));
+                               freeformat(head);
+                               return NULL;
+                       }
+                       cur->type=field;
+                       parsefield(cur, fmt+2, fmtend-1);
+                       fmt=fmtend+1;
+               } else {
+                       fmtend=fmt;
+                       do {
+                               fmtend+=1;
+                               fmtend=strchr(fmtend, '$');
+                       } while (fmtend && fmtend[1]!='{');
+
+                       if (!fmtend)
+                               fmtend=fmt+strlen(fmt);
+
+                       parsestring(cur, fmt, fmtend-1);
+                       fmt=fmtend;
+               }
+       }
+
+       return head;
+}
+
+
+static void dumpchain(struct lstitem* head) {
+       while (head) {
+               printf("Type: %s\n", (head->type==string) ? "string" : "field");
+               printf("Width: %d\n", head->width);
+               printf("Data: %s\n", head->data);
+               printf("\n");
+               head=head->next;
+       }
+}
+
+
+void show1package(const struct lstitem* head, struct pkginfo *pkg) {
+       struct varbuf vb, fb;
+
+       /* Make sure we have package info available, even if it's all empty. */
+       if (!pkg->installed.valid)
+               blankpackageperfile(&pkg->installed);
+
+       varbufinit(&vb);
+       varbufinit(&fb);
+
+       while (head) {
+               int ok;
+
+               ok=0;
+
+               if (head->type==string) {
+                       varbufprintf(&fb, "%s", head->data);
+                       ok=1;
+               } else if (head->type==field) {
+                       const struct fieldinfo* fip;
+
+                       for (fip=fieldinfos; fip->name; fip++) 
+                               if (strcasecmp(head->data, fip->name)==0)  {
+                                       size_t len;
+                                       char* i;
+
+                                       fip->wcall(&fb,pkg,&pkg->installed,fip);
+                                       /* Bugger, wcall adds the fieldname and a trailing newline we
+                                        * do not need. We should probably improve wcall to only do that
+                                        * optionally, but this will do for now (ie this is a TODO)
+                                        */
+                                       fb.buf[fb.used-1]='\0';
+                                       i=strchr(fb.buf, ':')+2;
+                                       len=strlen(i)+1;
+                                       memmove(fb.buf, i, len);
+
+                                       ok=1;
+                                       break;
+                               }
+
+                       if (!fip && pkg->installed.valid) {
+                               const struct arbitraryfield* afp;
+
+                               for (afp=pkg->installed.arbs; afp; afp=afp->next)
+                                       if (strcasecmp(head->data, afp->name)==0) {
+                                               varbufprintf(&fb, "%s", afp->value);
+                                               ok=1;
+                                               break;
+                                       }
+                       }
+               }
+
+               if (ok) {
+                       size_t len=strlen(fb.buf);
+                       if ((head->width>0) && (len>head->width))
+                               len=head->width;
+                       varbufaddbuf(&vb, fb.buf, len);
+               }
+
+               varbufreset(&fb);
+               head=head->next;
+       }
+
+       if (vb.buf) {
+               varbufaddc(&vb, '\0');
+               fputs(vb.buf,stdout);
+       }
+
+       varbuffree(&fb);
+       varbuffree(&vb);
+}
+