Bug 24695

Summary: [patch] pkg_info: prefix search for a package
Product: Base System Reporter: Edwin Groothuis <mavetju>
Component: binAssignee: Maxim Sobolev <sobomax>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.2-RELEASE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description Edwin Groothuis 2001-01-28 17:00:01 UTC
	Sometimes I need to find the know the description or the
	version of an installed package. Of course, pkg_info -a |
	grep string works fine, but userfriendly? By adding the -F
	option (fuzzy search), it will not check for the full name
	of the package but use the given pkg-name as a prefix in
	the package to search for.

How-To-Repeat: 
	[~] edwin@p6>pkg_info -F screen
	Information for screen-3.9.5:

	Comment:
	A multi-screen window manager
	[...]
Comment 1 Peter Pentchev 2001-01-28 17:44:49 UTC
On Sun, Jan 28, 2001 at 05:51:36PM +0100, mavetju@chello.nl wrote:
> 
> >Number:         24695
> >Category:       bin
> >Synopsis:       [patch] pkg_info: prefix search for a package
> >Originator:     Edwin Groothuis
> >Release:        FreeBSD 4.2-RELEASE i386
> >Organization:
> -
> >Environment:
> 
> 	pkg_install, HEAD tag
> 	main.c: 1.27
> 	pkg_info.1: 1.31
> 	perform.c: 1.32
> 	
> 
> >Description:
> 
> 	Sometimes I need to find the know the description or the
> 	version of an installed package. Of course, pkg_info -a |
> 	grep string works fine, but userfriendly? By adding the -F
> 	option (fuzzy search), it will not check for the full name
> 	of the package but use the given pkg-name as a prefix in
> 	the package to search for.
> 
> >How-To-Repeat:
> 
> 	[~] edwin@p6>pkg_info -F screen
> 	Information for screen-3.9.5:
> 
> 	Comment:
> 	A multi-screen window manager
> 	[...]

Hmm..  I've been meaning to try and do something like this for a long
time, but I haven't been able to find the time :)  Still, now that I've
taken a look at code someone has actually written, there are a couple
of comments.

Shouldn't the FuzzySearch opendir/readdir logic be outside of the pkg_do()
routine, and call pkg_do() once for every file it finds?  Currently you
stop at the very first file you find, which might not be so good if
multiple versions of a package are installed, or if the user deliberately
tries to query several packages with a common prefix (e.g. mysql-client/
mysql-server).

Apart from that, it's great that you've actually taken the time and
implemented this :)

G'luck,
Peter

-- 
This inert sentence is my body, but my soul is alive, dancing in the sparks of your brain.
Comment 2 Edwin Groothuis 2001-01-28 21:56:19 UTC
On Sun, Jan 28, 2001 at 07:44:49PM +0200, Peter Pentchev wrote:
> Shouldn't the FuzzySearch opendir/readdir logic be outside of the pkg_do()
> routine, and call pkg_do() once for every file it finds?  Currently you
> stop at the very first file you find, which might not be so good if

Yes, besides that pkg_do actually consists of two functions in one:
find the right files and display the information on them. I've
pulled them apart and I've added your suggestion.

> multiple versions of a package are installed, or if the user deliberately
> tries to query several packages with a common prefix (e.g. mysql-client/
> mysql-server).

That's something I hadn't thought about yet :-)

Here is a new patch, which implements your suggestion. It euh...
has two things now in it:

pkg_info -F stringsomehwereinthepackagename
pkg_info -P stringprefixofthepackagename

So people looking for the twenty versions of mysql are happy with
the -P and people which are looking for all packages related to
mysql are happy with the -F.

Edwin

-- 
Edwin Groothuis   |           Interested in MUDs? Visit Fatal Dimensions:
mavetju@chello.nl |                     http://fataldimensions.nl.eu.org/
------------------+               telnet://fataldimensions.nl.eu.org:4000



Index: main.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/main.c,v
retrieving revision 1.27
diff -u -r1.27 main.c
--- main.c	2000/12/05 11:02:19	1.27
+++ main.c	2001/01/28 21:55:10
@@ -28,11 +28,13 @@
   "$FreeBSD: src/usr.sbin/pkg_install/info/main.c,v 1.27 2000/12/05 11:02:19 sobomax Exp $";
 #endif
 
-static char Options[] = "acdDe:fhiIkl:LmopqrRst:v";
+static char Options[] = "acdDe:fFhiIkl:LmopPqrRst:v";
 
 int	Flags		= 0;
 Boolean AllInstalled	= FALSE;
 Boolean Quiet		= FALSE;
+Boolean FuzzySearch	= FALSE;
+Boolean PrefixSearch	= FALSE;
 char *InfoPrefix	= "";
 char PlayPen[FILENAME_MAX];
 char *CheckPkg		= NULL;
@@ -72,6 +74,10 @@
 	    Flags |= SHOW_PREFIX;
 	    break;
 
+	case 'P':
+	    PrefixSearch = TRUE;
+	    break;
+
 	case 'c':
 	    Flags |= SHOW_COMMENT;
 	    break;
@@ -86,6 +92,10 @@
 
 	case 'f':
 	    Flags |= SHOW_PLIST;
+	    break;
+
+	case 'F':
+	    FuzzySearch = TRUE;
 	    break;
 
 	case 'i':
Index: perform.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/perform.c,v
retrieving revision 1.32
diff -u -r1.32 perform.c
--- perform.c	2000/10/23 07:01:31	1.32
+++ perform.c	2001/01/28 21:55:10
@@ -32,6 +32,7 @@
 
 static int fname_cmp(const FTSENT **, const FTSENT **);
 static int pkg_do(char *);
+static int pkg_info(char *, Boolean);
 
 int
 pkg_perform(char **pkgs)
@@ -86,8 +87,6 @@
     Boolean installed = FALSE, isTMP = FALSE;
     char log_dir[FILENAME_MAX];
     char fname[FILENAME_MAX];
-    Package plist;
-    FILE *fp;
     struct stat sb;
     char *cp = NULL;
     int code = 0;
@@ -137,9 +136,49 @@
     /* It's not an ininstalled package, try and find it among the installed */
     else {
 	char *tmp;
+	extern Boolean FuzzySearch, PrefixSearch;
+
+	tmp = getenv(PKG_DBDIR);
+	if (tmp == NULL)
+	    tmp = DEF_LOG_DIR;
+	sprintf(log_dir, "%s/%s", tmp, pkg);
+	installed = TRUE;
 
-	sprintf(log_dir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
-		pkg);
+	/* If doing a prefix-search / fuzzy-search, go through all the files
+	 * in the pkg_db directory (as indicated by tmp) and see if they
+	 * matches the given description, then dump the information of it.
+	 */
+	if (FuzzySearch == TRUE || PrefixSearch == TRUE) {
+	    DIR *dirp = opendir(tmp);
+	    struct dirent *dp;
+	    Boolean found = FALSE;
+	    char *thispkg;
+
+	    while ((dp = readdir(dirp)) != NULL) {
+		if ((FuzzySearch == TRUE && strstr(dp->d_name, pkg) != NULL ) ||
+		    (PrefixSearch == TRUE && 
+			strncmp(pkg, dp->d_name, strlen(pkg)) == 0 )) {
+		    sprintf(log_dir, "%s/%s", tmp, dp->d_name);
+		    thispkg = dp->d_name;
+
+		    if (chdir(log_dir) == FAIL) {
+			warnx("can't change directory to '%s'!", log_dir);
+			return 1;
+		    }
+		    pkg_info(thispkg, installed);
+		    found++;
+		}
+	    }
+	    closedir(dirp);
+
+	    if (found==0) {
+		warnx("can't find a package prefixed with `%s'!", pkg);
+		return 1;
+	    }
+	    leave_playpen();
+	    return 0;
+	}
+
 	if (!fexists(log_dir)) {
 	    warnx("can't find package `%s' installed or in a file!", pkg);
 	    return 1;
@@ -148,16 +187,28 @@
 	    warnx("can't change directory to '%s'!", log_dir);
 	    return 1;
 	}
-	installed = TRUE;
     }
 
+    code = pkg_info(pkg, installed);
+ bail:
+    leave_playpen();
+    if (isTMP)
+	unlink(fname);
+    return code;
+}
+
+static int 
+pkg_info(char *pkg, Boolean installed) {
+    Package plist;
+    FILE *fp;
+    int code = 0;
+
     /* Suck in the contents list */
     plist.head = plist.tail = NULL;
     fp = fopen(CONTENTS_FNAME, "r");
     if (!fp) {
 	warnx("unable to open %s file", CONTENTS_FNAME);
-	code = 1;
-	goto bail;
+	return 1;
     }
     /* If we have a prefix, add it now */
     read_plist(&plist, fp);
@@ -211,10 +262,6 @@
 	    puts(InfoPrefix);
     }
     free_plist(&plist);
- bail:
-    leave_playpen();
-    if (isTMP)
-	unlink(fname);
     return code;
 }
 
Index: pkg_info.1
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/pkg_info.1,v
retrieving revision 1.31
diff -u -r1.31 pkg_info.1
--- pkg_info.1	2000/12/27 15:30:19	1.31
+++ pkg_info.1	2001/01/28 21:55:11
@@ -24,13 +24,13 @@
 .Nm pkg_info
 .Nd a utility for displaying information on software packages
 .Sh SYNOPSIS
-.Nm
-.Op Fl cdDfiIkLmopqrRsv
+.Nm pkg_info
+.Op Fl cdDfFiIkLmopPqrRsv
 .Op Fl e Ar package
 .Op Fl l Ar prefix
 .Op Fl t Ar template
 .Ar pkg-name [pkg-name ...]
-.Nm
+.Nm pkg_info
 .Fl a
 .Op Ar flags
 .Sh DESCRIPTION
@@ -54,6 +54,14 @@
 Show all currently installed packages.
 .It Fl v
 Turn on verbose output.
+.It Fl P
+Threat the 
+.Ar pkg-name
+as a prefix of the name of the package being searched for.
+.It Fl F
+Threat the 
+.Ar pkg-name
+as a string somewhere in the name of the package being searched for.
 .It Fl p
 Show the installation prefix for each package.
 .It Fl q
Comment 3 Peter Pentchev 2001-01-28 22:18:09 UTC
On Sun, Jan 28, 2001 at 10:56:19PM +0100, Edwin Groothuis wrote:
> On Sun, Jan 28, 2001 at 07:44:49PM +0200, Peter Pentchev wrote:
> > Shouldn't the FuzzySearch opendir/readdir logic be outside of the pkg_do()
> > routine, and call pkg_do() once for every file it finds?  Currently you
> > stop at the very first file you find, which might not be so good if
> 
> Yes, besides that pkg_do actually consists of two functions in one:
> find the right files and display the information on them. I've
> pulled them apart and I've added your suggestion.
> 
> > multiple versions of a package are installed, or if the user deliberately
> > tries to query several packages with a common prefix (e.g. mysql-client/
> > mysql-server).
> 
> That's something I hadn't thought about yet :-)
> 
> Here is a new patch, which implements your suggestion. It euh...
> has two things now in it:
> 
> pkg_info -F stringsomehwereinthepackagename
> pkg_info -P stringprefixofthepackagename
> 
> So people looking for the twenty versions of mysql are happy with
> the -P and people which are looking for all packages related to
> mysql are happy with the -F.

This one works great!

Hmm.. now to find somebody to look over the patch and possibly even
commit it.. :)

G'luck,
Peter

-- 
I've heard that this sentence is a rumor.
Comment 4 Maxim Sobolev freebsd_committer freebsd_triage 2001-02-05 14:35:53 UTC
Responsible Changed
From-To: freebsd-bugs->sobomax

I'll take this.
Comment 5 Maxim Sobolev freebsd_committer freebsd_triage 2001-02-08 18:36:23 UTC
State Changed
From-To: open->closed
Comment 6 Maxim Sobolev freebsd_committer freebsd_triage 2001-02-08 18:39:11 UTC
State Changed
From-To: closed->open
Comment 7 Maxim Sobolev freebsd_committer freebsd_triage 2001-02-08 18:40:58 UTC
State Changed
From-To: open->closed

Another similar, but more generic feature has been comitted. I have to give 
you a credit for the great idea. Thanks and please keep doing!