Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge branch 'master' of github.com:pkgng/pkgng
Matthew Seaman committed 13 years ago
commit 0e35cff0df742af772310d19b9e5a27e6de6789f
parent 5ab26d1
6 files changed +1019 -270
modified pkg/info.c
@@ -50,8 +50,8 @@ usage_info(void)
{
	fprintf(stderr, "usage: pkg info <pkg-name>\n");
	fprintf(stderr, "       pkg info -a\n");
-
	fprintf(stderr, "       pkg info [-eDgxXdrlBsqOf] <pkg-name>\n");
-
	fprintf(stderr, "       pkg info [-drlBsqfR] -F <pkg-file>\n\n");
+
	fprintf(stderr, "       pkg info [-BDdefgIlOqRrsXx] <pkg-name>\n");
+
	fprintf(stderr, "       pkg info [-BDdfIlqRrs] -F <pkg-file>\n\n");
	fprintf(stderr, "For more information see 'pkg help info'.\n");
}

@@ -65,9 +65,9 @@ exec_info(int argc, char **argv)
{
	struct pkgdb *db = NULL;
	struct pkgdb_it *it = NULL;
-
	int query_flags = PKG_LOAD_BASIC;
+
	int query_flags;
	struct pkg *pkg = NULL;
-
	unsigned int opt = 0;
+
	unsigned int opt = INFO_TAG_NAMEVER;
	match_t match = MATCH_EXACT;
	char *pkgname;
	char *pkgversion = NULL, *pkgversion2 = NULL;
@@ -79,19 +79,20 @@ exec_info(int argc, char **argv)
	int i, j;
	int sign = 0;
	int sign2 = 0;
+
	bool pkg_exists = false;
+
	bool origin_search = false;

	/* TODO: exclusive opts ? */
-
	while ((ch = getopt(argc, argv, "aDegxXEdrlBsqopOfF:R")) != -1) {
+
	while ((ch = getopt(argc, argv, "aDegxXEIdrlBsqopOfF:R")) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'O':
-
			/* this is only for ports compat */
-
			opt |= INFO_ORIGIN_SEARCH;
+
			origin_search = true;  /* only for ports compat */
			break;
		case 'e':
-
			opt |= INFO_EXISTS;
+
			pkg_exists = true;;
			retcode = 1;
			break;
		case 'g':
@@ -104,31 +105,30 @@ exec_info(int argc, char **argv)
			match = MATCH_EREGEX;
			break;
		case 'D':
-
			opt |= INFO_PRINT_MESSAGE;
-
			query_flags |= PKG_LOAD_BASIC;
+
			opt |= INFO_MESSAGE;
			break;
		case 'd':
-
			opt |= INFO_PRINT_DEP;
-
			query_flags |= PKG_LOAD_DEPS;
+
			opt |= INFO_DEPS;
+
			break;
+
		case 'I':
+
			opt |= INFO_COMMENT;
			break;
		case 'r':
-
			opt |= INFO_PRINT_RDEP;
-
			query_flags |= PKG_LOAD_RDEPS;
+
			opt |= INFO_RDEPS;
			break;
		case 'l':
-
			opt |= INFO_LIST_FILES;
-
			query_flags |= PKG_LOAD_FILES;
+
			opt |= INFO_FILES;
			break;
		case 'B':
-
			opt |= INFO_LIST_SHLIBS;
-
			query_flags |= PKG_LOAD_SHLIBS;
+
			opt |= INFO_SHLIBS;
			break;
		case 's':
-
			opt |= INFO_SIZE;
+
			opt |= INFO_FLATSIZE;
			break;
		case 'E': /* ports compatibility */
+
			/* FALLSTHROUGH */
		case 'q':
-
			opt |= INFO_QUIET;
+
			quiet = true;
			break;
		case 'o':
			opt |= INFO_ORIGIN;
@@ -138,14 +138,12 @@ exec_info(int argc, char **argv)
			break;
		case 'f':
			opt |= INFO_FULL;
-
			query_flags |= PKG_LOAD_CATEGORIES|PKG_LOAD_LICENSES|PKG_LOAD_OPTIONS;
			break;
		case 'F':
			file = optarg;
			break;
		case 'R':
			opt |= INFO_RAW;
-
			query_flags |= PKG_LOAD_FILES|PKG_LOAD_DIRS|PKG_LOAD_CATEGORIES|PKG_LOAD_LICENSES|PKG_LOAD_OPTIONS|PKG_LOAD_SCRIPTS|PKG_LOAD_USERS|PKG_LOAD_GROUPS|PKG_LOAD_DEPS|PKG_LOAD_SHLIBS;
			break;
		default:
			usage_info();
@@ -161,12 +159,27 @@ exec_info(int argc, char **argv)

	if (argc == 0 && file == NULL && match != MATCH_ALL) {
		/* which -O bsd.*.mk always execpt clean output */
-
		if (opt & INFO_ORIGIN_SEARCH)
+
		if (origin_search)
			return (EX_OK);
		usage_info();
		return (EX_USAGE);
	}

+
	/* When no other data is requested, default is to print
+
	 * 'name-ver comment' For -O, just print name-ver */
+
	if (!origin_search && (opt & INFO_ALL) == 0 && match == MATCH_ALL) 
+
		opt |= INFO_COMMENT;
+

+
	/* Special compatibility: handle -O and -q -O */
+
	if (origin_search) {
+
		if (quiet) {
+
			opt = INFO_TAG_NAMEVER;
+
			quiet = false;
+
		} else {
+
			opt = INFO_TAG_NAMEVER|INFO_COMMENT;
+
		}
+
	}
+

	if (file != NULL) {
		if (pkg_open(&pkg, file, NULL) != EPKG_OK) {
			return (1);
@@ -184,7 +197,7 @@ exec_info(int argc, char **argv)
		if (match == MATCH_ALL)
			return (EX_OK);

-
		if ((opt & INFO_QUIET) == 0)
+
		if (!quiet)
			printf("No packages installed.\n");

		return (EX_UNAVAILABLE);
@@ -294,11 +307,12 @@ exec_info(int argc, char **argv)

		/* ports infrastructure expects pkg info -q -O to always return 0 even
		 * if the ports doesn't exists */
-
		if (opt & INFO_ORIGIN_SEARCH)
+
		if (origin_search)
			gotone = true;

		/* end of compatibility hacks */

+
		query_flags = info_flags(opt);
		while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
			gotone = true;
			const char *version;
@@ -352,7 +366,7 @@ exec_info(int argc, char **argv)
					break;
				}
			}
-
			if (opt & INFO_EXISTS)
+
			if (pkg_exists)
				retcode = EX_OK;
			else
				print_info(pkg, opt);
@@ -362,7 +376,7 @@ exec_info(int argc, char **argv)
		}

		if (retcode == EX_OK && !gotone && match != MATCH_ALL) {
-
			if ((opt & INFO_QUIET) == 0)
+
			if (!quiet)
				warnx("No package(s) matching %s", argv[i]);
			retcode = EX_SOFTWARE;
		}
modified pkg/pkg-info.8
@@ -27,10 +27,10 @@
.Nm
.Fl a
.Nm
-
.Op Fl eDgxXEdrlsqopOfRF
+
.Op Fl BDdefgIlOqRrsXx
.Ar <pkg-name>
.Nm
-
.Op Fl drlsq
+
.Op Fl BDdfIlqRrs
.Fl F Ar <pkg-file>
.Sh DESCRIPTION
.Nm
modified pkg/pkg-search.8
@@ -15,79 +15,359 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd February 16, 2012
+
.Dd July 11, 2012
.Dt PKG-SEARCH 8
.Os
.Sh NAME
.Nm "pkg search"
-
.Nd searches in remote package repositories
+
.Nd search package repository catalogues
.Sh SYNOPSIS
.Nm
-
.Ar pkg-name
-
.Nm
-
.Op Fl fDsqop
-
.Ar pkg-name
+
.Op Fl egxX
+
.Op Fl r Ar repo
+
.Op Fl S Ar search
+
.Op Fl L Ar label
+
.Op Fl M Ar mod
+
.Ar pattern
.Nm
-
.Op Fl gexXcdfDsqop
+
.Op Fl cDdefgopqXx
+
.Op Fl r Ar repo
.Ar pattern
.Sh DESCRIPTION
.Nm
-
is used for searching in the remote package repositories
-
and it displays the requested information for the matching
-
packages.
+
is used for searching package repository catalogues.
+
Packages available for installation can be matched by name, by name
+
and version, by origin or by text in the package comments or package
+
descriptions.
+
The output defaults to displaying the field matched by the search
+
term, but any of the searchable fields may be displayed.
+
The output may be modified to additionally show many other package
+
data available from the repository catalogues.
.Pp
-
.Nm
-
will search for the given pattern in the remote package
-
repositories, which are defined in the
-
.Xr pkg.conf 5
-
file.
+
It is recommended to update the local copies of the repository
+
catalogues before running
+
.Nm .
+
See
+
.Xr pkg-update 8 .
+
Package repositories are defined in the
+
.Fa pkg.conf
+
file; see
+
.Xr pkg.conf 5.
.Sh OPTIONS
The following options are supported by
.Nm :
.Bl -tag -width F1
+
.It Fl c
+
Search for packages with comment text matching
+
.Ar pattern .
+
Equivalent to
+
.Fl "S comment" . 
+
.It Fl D
+
Display the list of packages depended on by each matched package.
+
Equivalent to
+
.Fl "M depends-on" .
+
.It Fl d
+
Search for packages with description text matching
+
.Ar pattern .
+
Equivalent to
+
.Fl "S description" .
.It Fl e
-
Treat
.Ar pattern
-
as exact pattern
+
should be an exact match against the search field.
+
.It Fl f
+
Show ``full'' information about the package.
+
Equivalent to
+
.Fl "M full" . 
.It Fl g
Treat
.Ar pattern
-
as a shell glob pattern.
-
.It Fl x
-
Treat
-
.Ar pattern
-
as a regular expression.
+
as a shell globbing expression.
+
The glob pattern must match the entire field being seached.
+
.It Fl L Ar label
+
Select which identifying label is printed for each matched package,
+
unless
+
.Fl q
+
is used.
+
Several different fields from the repository catalogue database may be
+
used to search on, or to generate the label, as indicated by the
+
.Ar label
+
argument.
+
See the 
+
.Qq Sx Search and Label Options
+
section for details.
+
If unspecified,
+
.Ar label
+
is set to the same as the value searched via the
+
.Fl S Ar search
+
option.
+
.It Fl M Ar mod
+
Modify the output by adding an additional field to the result.
+
Multiple fields can be added by using additional
+
.Fl M Ar mod
+
flags.  See the
+
.Qq Sx Output Modifier Options
+
section for details.
+
.It Fl o
+
List packages by origin for each package matching
+
.Ar pattern .
+
Equivalent to
+
.Fl "L origin" .
+
.It Fl p
+
Display the package installation prefix for each matched package.
+
Equivalent to
+
.Fl "M prefix" . 
+
.It Fl q
+
Be ``quiet''.
+
Produce less output.
+
In particular don't show an identifying label field for each package.
+
.It Fl r Ar repo
+
In multi-repo mode, select only the repository catalogue from
+
.Sy repo
+
to search.
+
By default all known repository catalogues are searched.
+
.It Fl S Ar search
+
Specify the field to search the repository catalogue on.
+
If unspecified, searches on
+
.Ar pkg-name
+
unless the search term contains a 
+
.Sy /
+
character, when it searches on port
+
.Ar origin .
+
Output will be sorted in order of the
+
.Ar search
+
field.
+
See the
+
.Qq Sx Search and Label Options
+
sections for more details.
+
.It Fl s
+
Display the installed size of matched packages.
+
Equivalent to
+
.Fl "M size" . 
.It Fl X
Treat
.Ar pattern
as an extended regular expression.
-
.It Fl c
-
Search for
-
.Ar pattern
-
in the package comment one-line description.
-
.It Fl d
-
Search for
-
.Ar pattern
-
in the package desription.
-
.It Fl f
-
Displays full information about the matching packages.
-
.It Fl D
-
Displays the dependencies of
-
.Ar pattern
-
.It Fl s
-
Displays the size of the package
-
.It Fl q
-
Be ``quiet''.
-
Prints only the requested information without
-
displaying many hints.
-
.It Fl o
-
Displays
+
Matches any substring of the search field unless explicit beginning
+
or ending anchor terms are used.
+
.It Fl x
+
Treat
.Ar pattern
-
origin.
-
.It Fl p
-
Displays the installation prefix for each package matching
+
as a regular expression.  This is the default.
+
Matches any substring of the search field unless explicit beginning
+
or ending anchor terms are used.
+
.El
+
.Ss Search and Label Options
+
The following database fields (or composites of several fields) can
+
be used both for searching for a match to the given
.Ar pattern
+
and as identifying labels for the block of output for each package.
+
.Bl -tag -width 2n
+
.It Sy comment
+
The one line comment field describing the port, derived from the
+
.Cm COMMENT
+
variable in the port's
+
.Fa Makefile .
+
When chosen as a label option, the output format will additionally
+
include the packge name, equivalent to
+
.Fl "L pkg-name"
+
.Fl "M comment" .
+
When chosen as a search option, only the
+
.Sy comment
+
field is used for sorting the output.
+
.It Sy description
+
The multi-line package description from the
+
.Fa pkg-descr
+
file in the port.
+
This does include the
+
.Cm WWW
+
URL reference, if any, from that file.
+
When chosen as a label option, the output format will additionally
+
include the package name, equivalent to
+
.Fl "L pkg-name"
+
.Fl "M description" .
+
When chosen as a search option, only the
+
.Sy description
+
field is used for sorting the output.
+
.It Sy name
+
The name of the package, derived from the
+
.Cm PORTNAME
+
variable in the port's
+
.Fa Makefile .
+
.It Sy origin
+
The port origin, in the format
+
.Fa category/port ,
+
that the package was compiled from.
+
.It Sy pkg-name
+
The package name in the format
+
.Sy name Ns - Ns Cm version .
+
The same as the
+
.Cm PKGNAME
+
variable in the port's
+
.Fa Makefile .
.El
+
.Pp
+
Any unambiguous prefix of the label name may be used on the command line.
+
Thus
+
.Fl "Sd" ,
+
.Fl "S descr"
+
and
+
.Fl "S description"
+
are all equivalent.
+
.Ss Output Modifier Options
+
Additional data from the repository catalogue to print for each matched
+
package.
+
Multiple output modifiers can be combined.
+
Where more than one output field is required, either because multiple
+
.Fl M Ar mod
+
options were given, or one or more
+
.Fl M Ar mod
+
option was combined with the
+
.Fl "L comment"
+
or
+
.Fl "L description"
+
options, then each output field will be tagged with the field name.
+
.Bl -tag -width 2n
+
.It Sy arch
+
The architecture string indicating what OS version and CPU architecture
+
the package is suitable for.  For example,
+
.Ar freebsd:9:x86:64
+
indicates a package suitable for FreeBSD 9.x running on an amd64 processor,
+
while
+
.Ar freebsd:*
+
indicates an architecture independent package suitable for any version of
+
FreeBSD.
+
.It Sy categories
+
All categories, real and virtual, the underlying package belongs to,
+
derived from the
+
.Cm CATEGORIES
+
variable in the port's
+
.Fa Makefile .
+
.It Sy comment
+
The one line comment field describing the port, derived from the
+
.Cm COMMENT
+
variable in the port's
+
.Fa Makefile .
+
.It Sy depends-on
+
The list of packages the named package depends on.
+
Dependency packages are listed in the format
+
.Sy name Ns - Ns Cm version
+
one per line.
+
If the port has no dependencies, nothing will be output for
+
this field, including suppressing the tag name when multiple
+
output fields are requested.
+
.It Sy description
+
The multi-line package description from the
+
.Fa pkg-descr
+
file in the port.
+
This does include the
+
.Cm WWW
+
URL reference, if any, from that file.
+
.It Sy full
+
Show a standard set of fields, equivalent to a combination of the
+
.Sy name ,
+
.Sy version ,
+
.Sy origin ,
+
.Sy prefix ,
+
.Sy repository ,
+
.Sy categories ,
+
.Sy license ,
+
.Sy maintainer ,
+
.Sy www ,
+
.Sy comment ,
+
.Sy options ,
+
.Sy shared-libs ,
+
.Sy size ,
+
.Sy pkg-size
+
and
+
.Sy descr
+
fields, in that order.
+
.It Sy licenses
+
Displays a list of all the licenses the package is relesed under on a
+
single line.
+
Where more than one license applies, indicate if the terms of all
+
licenses should apply
+
.Sy (&)
+
or if one or more licenses may be selected out of those available
+
.Sy (|) .
+
.It Sy maintainer
+
Display the maintainer's e-mail address.
+
.It Sy name
+
Display the port name, which is derived from the
+
.Cm PORTNAME
+
variable in the port's
+
.Fa Makefile .
+
.It Sy options
+
Displays a list of the port options and their state (
+
.Sy on
+
or
+
.Sy off )
+
when the package was built.
+
If the package does not have any options to set, nothing will be
+
output for this field, including suppressing the tag name when
+
multiple output fields are requested.
+
.It Sy pkg-size
+
Display the size of the compressed package tarball, ie. how much would
+
need to be downloaded from the repository.
+
.It Sy prefix
+
Display the installation prefix for the package, usually
+
.Fa /usr/local .
+
.It Sy repository
+
Displays the repository label and the corresponding base Url for the
+
repository.
+
In multi-repo mode, the repository label and URL are one of the pairs
+
defined in
+
.Fa pkg.conf .  
+
In normal mode the label is always ``remote'', and the URL is the
+
value of
+
.Cm PACKAGESITE .
+
.It Sy required-by
+
Displays all of the packages in the repository that require the named
+
package as a dependency.
+
Dependency packages are listed in the format
+
.Sy name Ns - Ns Cm version
+
one per line.
+
If the no other packages require the named package, nothing will be
+
output for this field, including suppressing the tag name when
+
multiple output fields are requested.
+
.It Sy shared-libs
+
If the package contains dynamically linked FreeBSD ELF binaries,
+
display a list of all of the shared libraries other than those from
+
the base system required for those binaries to run.
+
Shared libraries for foreign (eg. Linux) binaries run
+
under emulation will not be displayed.
+
If the package does not require any shared libraries, nothing will be
+
output for this field including suppressing the tag name when multiple
+
fields are requested.
+
.It Sy size
+
Display the total amount of filesystem space the package files will
+
take up once unpacked and installed.
+
.It Sy url
+
Display the URL that would be used to download the package from the
+
repository.
+
.It Sy www
+
Display the general URL, if any, for the project developing the
+
software used in the package.
+
This is extracted from the
+
.Fa pkg-descr
+
file in the port. 
+
.El
+
.Pp
+
Any unambiguous prefix of the modifier name may be used on the command
+
line.
+
Thus
+
.Fl "Mm" ,
+
.Fl "M maint"
+
and
+
.Fl "M maintainer"
+
are all equivalent,
+
but you need to use at least
+
.Fl "M si"
+
and
+
.Fl "M sh"
+
to distinguish
+
.Cm size
+
from
+
.Cm shared-libs .
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm .
@@ -96,6 +376,7 @@ See
for further description.
.Bl -tag -width ".Ev NO_DESCRIPTIONS"
.It Ev PACKAGESITE
+
.It Ev PKG_DBDIR
.It Ev PKG_MULTIREPOS
.El
.Sh FILES
modified pkg/pkgcli.h
@@ -146,24 +146,63 @@ int exec_which(int, char **);
void usage_which(void);

/* utils */
-
#define INFO_PRINT_DEP (1<<0)
-
#define INFO_PRINT_RDEP (1<<1)
-
#define INFO_EXISTS (1<<2)
-
#define INFO_LIST_FILES (1<<3)
-
#define INFO_SIZE (1<<4)
-
#define INFO_QUIET (1<<5)
-
#define INFO_ORIGIN (1<<6)
-
#define INFO_ORIGIN_SEARCH (1<<7)
-
#define INFO_PREFIX (1<<8)
-
#define INFO_FULL (1<<9)
-
#define INFO_RAW (1<<10)
-
#define INFO_LIST_SHLIBS (1<<11)
-
#define INFO_PRINT_MESSAGE (1<<12)
+

+
/* These are the fields of the Full output, in order */
+
#define INFO_NAME	(1<<0)
+
#define INFO_VERSION	(1<<1)
+
#define INFO_ORIGIN	(1<<2)
+
#define INFO_PREFIX	(1<<3)
+
#define INFO_REPOSITORY	(1<<4)
+
#define INFO_CATEGORIES	(1<<5)
+
#define INFO_LICENSES	(1<<6)
+
#define INFO_MAINTAINER	(1<<7)
+
#define INFO_WWW	(1<<8)
+
#define INFO_COMMENT	(1<<9)
+
#define INFO_OPTIONS	(1<<10)
+
#define INFO_SHLIBS	(1<<11)
+
#define INFO_FLATSIZE	(1<<12)
+
#define INFO_PKGSIZE	(1<<13)
+
#define INFO_DESCR	(1<<14)
+

+
/* Other fields not part of the Full output */
+
#define INFO_MESSAGE	(1<<15)
+
#define INFO_DEPS	(1<<16)
+
#define INFO_RDEPS	(1<<17)
+
#define INFO_FILES	(1<<18)
+
#define INFO_DIRS	(1<<19)
+
#define INFO_USERS	(1<<20)
+
#define INFO_GROUPS	(1<<21)
+
#define INFO_ARCH	(1<<22)
+
#define INFO_REPOURL	(1<<23)
+

+
#define INFO_LASTFIELD	INFO_REPOURL
+
#define INFO_ALL	(((INFO_LASTFIELD) << 1) - 1)
+

+
/* Identifying tags */
+
#define INFO_TAG_NAME		(1<<28)
+
#define INFO_TAG_ORIGIN		(1<<29)
+
#define INFO_TAG_NAMEVER	(1<<30)
+

+
/* Output YAML format */
+
#define INFO_RAW	(1<<31)
+

+
/* Everything in the 'full' package output */
+
#define INFO_FULL	(INFO_NAME|INFO_VERSION|INFO_ORIGIN|INFO_PREFIX| \
+
			 INFO_REPOSITORY|INFO_CATEGORIES|INFO_LICENSES|  \
+
			 INFO_MAINTAINER|INFO_WWW|INFO_COMMENT|          \
+
			 INFO_OPTIONS|INFO_SHLIBS|INFO_FLATSIZE|         \
+
			 INFO_PKGSIZE|INFO_DESCR)
+

+
/* Everything that can take more than one line to print */
+
#define INFO_MULTILINE	(INFO_OPTIONS|INFO_SHLIBS|INFO_DESCR|INFO_MESSAGE| \
+
			 INFO_DEPS|INFO_RDEPS|INFO_FILES|INFO_DIRS)

bool query_yesno(const char *msg, ...);
+
int info_flags(unsigned int opt);
void print_info(struct pkg * const pkg, unsigned int opt);
char *absolutepath(const char *src, char *dest, size_t dest_len);
-
void print_jobs_summary(struct pkg_jobs *j, pkg_jobs_t type, const char *msg, ...);
+
void print_jobs_summary(struct pkg_jobs *j, pkg_jobs_t type,
+
			const char *msg, ...);
struct sbuf *exec_buf(const char *cmd);

int event_callback(void *data, struct pkg_event *ev);
@@ -180,7 +219,10 @@ struct query_flags {
};

void print_query(struct pkg *pkg, char *qstr, char multiline);
-
int format_sql_condition(const char *str, struct sbuf *sqlcond, bool for_remote);
-
int analyse_query_string(char *qstr, struct query_flags *q_flags, const unsigned int q_flags_len, int *flags, char *multiline);
+
int format_sql_condition(const char *str, struct sbuf *sqlcond,
+
			 bool for_remote);
+
int analyse_query_string(char *qstr, struct query_flags *q_flags,
+
			 const unsigned int q_flags_len, int *flags,
+
			 char *multiline);

#endif
modified pkg/search.c
@@ -30,17 +30,200 @@
#include <string.h>
#include <unistd.h>
#include <sysexits.h>
+
#include <err.h>

#include <pkg.h>

#include "pkgcli.h"

+
typedef struct _cliopt {
+
	const char *option;
+
	char key;
+
} cliopt;
+

+
/* an option string should not be a prefix of any other option string */ 
+
static const cliopt search_label[] = {
+
	{ "comment",     'c'  },
+
	{ "description", 'd'  },
+
	{ "name",        'n'  },
+
	{ "origin",      'o'  },
+
	{ "pkg-name",    'p'  },
+
	{ NULL,          '\0' },
+
};
+

+
static const cliopt modifiers[] = {
+
	{ "arch",         'a'  },
+
	{ "categories",   'C'  },
+
	{ "comment",      'c'  },
+
	{ "depends-on",   'd'  },
+
	{ "description",  'D'  },
+
	{ "full",         'f'  },
+
	{ "licenses",     'l'  },
+
	{ "maintainer",   'm'  },
+
	{ "name",         'n'  },
+
	{ "options",      'o'  },
+
	{ "pkg-size",	  'P'  },
+
	{ "prefix",       'p'  },
+
	{ "repository",   'R'  },
+
	{ "required-by",  'r'  },
+
	{ "shared-libs",  'S'  },
+
	{ "size",         's'  },
+
	{ "url",          'u'  },
+
	{ "www",          'w'  },
+
	{ NULL,           '\0' },
+
};	
+

+
static char
+
match_optarg(const cliopt *optlist, const char *opt)
+
{
+
	int i, matched = -1;
+
	char key = '\0';
+
	size_t optlen;
+

+
	optlen = strlen(opt);
+

+
	/* Match any unique prefix from  optlist */
+
	for (i = 0; optlist[i].option != NULL; i++) {
+
		if (strncmp(opt, optlist[i].option, optlen) != 0)
+
			continue;
+
		if (matched > 0) {
+
			warnx("\"%s\" is ambiguous: did you mean "
+
			      "\"%s\" or \"%s\"?", opt,
+
			      optlist[matched].option, optlist[i].option);
+
			key = '\0';
+
			break;
+
		}
+
		matched = i;
+
		key = optlist[i].key;
+
	}
+
	return (key);
+
}
+

+
static pkgdb_field
+
search_label_opt(const char *optionarg)
+
{
+
	pkgdb_field field;
+

+
	/* label options */
+
	switch(match_optarg(search_label, optionarg)) {
+
	case 'o':
+
		field = FIELD_ORIGIN;
+
		break;
+
	case 'n':
+
		field = FIELD_NAME;
+
		break;
+
	case 'p':
+
		field = FIELD_NAMEVER;
+
		break;
+
	case 'c':
+
		field = FIELD_COMMENT;
+
		break;
+
	case 'd':
+
		field = FIELD_DESC;
+
		break;
+
	default:
+
		usage_search();
+
		errx(EX_USAGE, "Unknown search/label option: %s", optionarg);
+
		/* NOTREACHED */
+
	}
+
	return field;
+
}
+

+
static unsigned int
+
modifier_opt(const char *optionarg)
+
{
+
	unsigned int opt;
+

+
	/* output modifiers */
+
	switch(match_optarg(modifiers, optionarg)) {
+
	case 'a':
+
		opt = INFO_ARCH;
+
		break;
+
	case 'C':
+
		opt = INFO_CATEGORIES;
+
		break;
+
	case 'c':
+
		opt = INFO_COMMENT;
+
		break;
+
	case 'd':
+
		opt = INFO_DEPS;
+
		break;
+
	case 'D':
+
		opt = INFO_DESCR;
+
		break;
+
	case 'f':
+
		opt = INFO_FULL;
+
		break;
+
	case 'l':
+
		opt = INFO_LICENSES;
+
		break;
+
	case 'm':
+
		opt = INFO_MAINTAINER;
+
		break;
+
	case 'n':
+
		opt = INFO_NAME;
+
		break;
+
	case 'o':
+
		opt = INFO_OPTIONS;
+
		break;
+
	case 'P':
+
		opt = INFO_PKGSIZE;
+
		break;
+
	case 'p':
+
		opt = INFO_PREFIX;
+
		break;
+
	case 'R':
+
		opt = INFO_REPOSITORY;
+
		break;
+
	case 'r':
+
		opt = INFO_RDEPS;
+
		break;
+
	case 'S':
+
		opt = INFO_SHLIBS;
+
		break;
+
	case 's':
+
		opt = INFO_FLATSIZE;
+
		break;
+
	case 'u':
+
		opt = INFO_REPOURL;
+
		break;
+
	case 'v':
+
		opt = INFO_VERSION;
+
		break;
+
	case 'w':
+
		opt = INFO_WWW;
+
		break;
+
	default:
+
		usage_search();
+
		errx(EX_USAGE, "Unkown modifier option %s", optionarg);
+
		/* NOTREACHED */
+
	}
+
	return opt;
+
}
+

void
usage_search(void)
{
-
	fprintf(stderr, "usage: pkg search [-r reponame] <pkg-name>\n");
-
	fprintf(stderr, "       pkg search [-r reponame] [-fDsqop] <pkg-name>\n");
-
	fprintf(stderr, "       pkg search [-r reponame] [-egxXcdfDsqop] <pattern>\n\n");
+
	int i, n;
+

+
	fprintf(stderr, "usage: pkg search [-egXx] [-r repo] [-S search] "
+
	    "[-L label] [-M mod]... <pkg-name>\n");
+
	fprintf(stderr, "       pkg search [-cDdefgopqXx] [-r repo] "
+
	    "<pattern>\n\n");
+
	n = fprintf(stderr, "       Search and Label options:");
+
	for (i = 0; search_label[i].option != NULL; i++) {
+
		if (n > 72)
+
			n = fprintf(stderr, "\n            ");
+
		n += fprintf(stderr, " %s", search_label[i].option);
+
	}
+
	fprintf(stderr, "\n");
+
	n = fprintf(stderr, "       Output Modifiers:");
+
	for (i = 0; modifiers[i].option != NULL; i++) {
+
		if (n > 68)
+
			n = fprintf(stderr, "\n            ");
+
		n += fprintf(stderr, " %s", modifiers[i].option);
+
	}
+
	fprintf(stderr, "\n");
	fprintf(stderr, "For more information see 'pkg help search'.\n");
}

@@ -50,56 +233,65 @@ exec_search(int argc, char **argv)
	const char *pattern = NULL;
	const char *reponame = NULL;
	int ret = EPKG_OK, ch;
-
	int flags = PKG_LOAD_BASIC;
+
	int flags;
	unsigned int opt = 0;
	match_t match = MATCH_REGEX;
-
	pkgdb_field field = FIELD_NAME;
+
	pkgdb_field search = FIELD_NONE;
+
	pkgdb_field label = FIELD_NONE;
	struct pkgdb *db = NULL;
	struct pkgdb_it *it = NULL;
	struct pkg *pkg = NULL;
	bool atleastone = false;

-
	while ((ch = getopt(argc, argv, "gxXcdr:fDsqop")) != -1) {
+
	while ((ch = getopt(argc, argv, "cDdefgL:M:opqr:S:sXx")) != -1) {
		switch (ch) {
+
		case 'c':	/* Same as -S comment */
+
			search = search_label_opt("comment");
+
			break;
+
		case 'D':	/* Same as -M depends-on  */
+
			opt |= modifier_opt("depends-on");
+
			break;
+
		case 'd':	/* Same as -S description */
+
			search = search_label_opt("description");
+
			break;
		case 'e':
			match = MATCH_EXACT;
			break;
+
		case 'f':	/* Same as -M full */
+
			opt |= modifier_opt("full");
+
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
-
		case 'x':
-
			match = MATCH_REGEX;
+
		case 'L':
+
			label = search_label_opt(optarg);
			break;
-
		case 'X':
-
			match = MATCH_EREGEX;
+
		case 'M':
+
			opt |= modifier_opt(optarg);
+
			break;
+
		case 'o':	/* Same as -L origin */
+
			label = search_label_opt("origin");
			break;
-
		case 'c':
-
			field = FIELD_COMMENT;
+
		case 'p':	/* Same as -M prefix */
+
			opt |= modifier_opt("prefix");
			break;
-
		case 'd':
-
			field = FIELD_DESC;
+
		case 'q':
+
			quiet = true;
			break;
		case 'r':
			reponame = optarg;
-
		case 'f':
-
			opt |= INFO_FULL;
-
			flags |= PKG_LOAD_CATEGORIES|PKG_LOAD_LICENSES|PKG_LOAD_OPTIONS|PKG_LOAD_SHLIBS;
-
			break;
-
		case 'D':
-
			opt |= INFO_PRINT_DEP;
-
			flags |= PKG_LOAD_DEPS;
			break;
-
		case 's':
-
			opt |= INFO_SIZE;
+
		case 'S':
+
			search = search_label_opt(optarg);
			break;
-
		case 'q':
-
			opt |= INFO_QUIET;
+
		case 's':	/* Same as -M size */
+
			opt |= modifier_opt("size");
			break;
-
		case 'o':
-
			opt |= INFO_ORIGIN;
+
		case 'X':
+
			match = MATCH_EREGEX;
			break;
-
		case 'p':
-
			opt |= INFO_PREFIX;
+
		case 'x':
+
			match = MATCH_REGEX;
			break;
		default:
			usage_search();
@@ -120,17 +312,45 @@ exec_search(int argc, char **argv)
		fprintf(stderr, "Pattern must not be empty!\n");
		return (EX_USAGE);
	}
-
	if (strchr(pattern, '/') != NULL)
-
		field = FIELD_ORIGIN;
+
	if (search == FIELD_NONE) {
+
		if (strchr(pattern, '/') != NULL)
+
			search = FIELD_ORIGIN;
+
		else
+
			search = FIELD_NAMEVER; /* Default search */
+
	}
+
	if (label == FIELD_NONE)
+
		label = search; /* By default, show what was searched  */
+

+
	switch(label) {
+
	case FIELD_NONE:
+
		break;		/* should never happen */
+
	case FIELD_ORIGIN:
+
		opt |= INFO_TAG_ORIGIN;
+
		break;
+
	case FIELD_NAME:
+
		opt |= INFO_TAG_NAME;
+
		break;
+
	case FIELD_NAMEVER:
+
		opt |= INFO_TAG_NAMEVER;
+
		break;
+
	case FIELD_COMMENT:
+
		opt |= INFO_TAG_NAMEVER|INFO_COMMENT;
+
		break;
+
	case FIELD_DESC:
+
		opt |= INFO_TAG_NAMEVER|INFO_DESCR;
+
		break;
+
	}

	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK)
		return (EX_IOERR);

-
	if ((it = pkgdb_search(db, pattern, match, field, reponame)) == NULL) {
+
	if ((it = pkgdb_search(db, pattern, match, search, reponame)) ==
+
	    NULL) {
		pkgdb_close(db);
		return (EX_IOERR);
	}

+
	flags = info_flags(opt);
	while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) {
		print_info(pkg, opt);
		atleastone = true;
@@ -143,8 +363,5 @@ exec_search(int argc, char **argv)
	if (!atleastone)
		ret = EPKG_FATAL;

-
	if (ret == EPKG_END)
-
		ret = EPKG_OK;
-

-
	return ((ret == EPKG_OK) ? EX_OK : EX_SOFTWARE);
+
	return ((ret == EPKG_OK || ret == EPKG_END) ? EX_OK : EX_SOFTWARE);
}
modified pkg/utils.c
@@ -2,6 +2,7 @@
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
+
 * Copyright (c) 2012 Matthew Seaman <matthew@FreeBSD.org>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
@@ -54,7 +55,7 @@ query_yesno(const char *msg, ...)
	else if (c == '\n' || c == EOF)
		return false;

-
	while((c = getchar()) != '\n' && c != EOF)
+
	while ((c = getchar()) != '\n' && c != EOF)
		continue;

	return r;
@@ -128,167 +129,361 @@ absolutepath(const char *src, char *dest, size_t dest_len) {
	return &dest[0];
}

+
/* what the pkg needs to load in order to display the requested info */
+
int
+
info_flags(unsigned int opt)
+
{
+
	int flags = PKG_LOAD_BASIC;
+

+
	if (opt & INFO_CATEGORIES)
+
		flags |= PKG_LOAD_CATEGORIES;
+
	if (opt & INFO_LICENSES)
+
		flags |= PKG_LOAD_LICENSES;
+
	if (opt & INFO_OPTIONS)
+
		flags |= PKG_LOAD_OPTIONS;
+
	if (opt & INFO_SHLIBS)
+
		flags |= PKG_LOAD_SHLIBS;
+
	if (opt & INFO_DEPS)
+
		flags |= PKG_LOAD_DEPS;
+
	if (opt & INFO_RDEPS)
+
		flags |= PKG_LOAD_RDEPS;
+
	if (opt & INFO_FILES)
+
		flags |= PKG_LOAD_FILES;
+
	if (opt & INFO_DIRS)
+
		flags |= PKG_LOAD_DIRS;
+
	if (opt & INFO_USERS)
+
		flags |= PKG_LOAD_USERS;
+
	if (opt & INFO_GROUPS)
+
		flags |= PKG_LOAD_GROUPS;
+

+
	return flags;
+
}
+

void
-
print_info(struct pkg * const pkg, unsigned int opt)
+
print_info(struct pkg * const pkg, unsigned int options)
{
-
	struct pkg_dep *dep = NULL;
-
	struct pkg_file *file = NULL;
-
	struct pkg_category *cat = NULL;
-
	struct pkg_license *lic = NULL;
-
	struct pkg_option *option = NULL;
-
	struct pkg_shlib *shlib = NULL;
+
	struct pkg_category *cat    = NULL;
+
	struct pkg_dep	    *dep    = NULL;
+
	struct pkg_dir	    *dir    = NULL;
+
	struct pkg_file	    *file   = NULL;
+
	struct pkg_group    *group  = NULL;
+
	struct pkg_license  *lic    = NULL;
+
	struct pkg_option   *option = NULL;
+
	struct pkg_shlib    *shlib  = NULL;
+
	struct pkg_user	    *user   = NULL;
	bool multirepos_enabled = false;
-
	char buf[BUFSIZ];
-
	char *m;
+
	bool print_tag = false;
	char size[7];
	const char *name, *version, *prefix, *origin, *reponame, *repourl;
-
	const char *maintainer, *www, *comment, *desc, *message;
+
	const char *maintainer, *www, *comment, *desc, *message, *arch;
+
	const char *repopath;
+
	char *m;
+
	unsigned opt;
	int64_t flatsize, newflatsize, newpkgsize;
	lic_t licenselogic;
+
	int cout = 0;		/* Number of characters output */
+
	int info_num;		/* Number of different data items to print */

	pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled);

-
	pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version, PKG_PREFIX, &prefix,
-
	    PKG_ORIGIN, &origin, PKG_REPONAME, &reponame, PKG_REPOURL, &repourl,
-
	    PKG_MAINTAINER, &maintainer, PKG_WWW, &www, PKG_COMMENT, &comment,
-
	    PKG_DESC, &desc, PKG_FLATSIZE, &flatsize, PKG_NEW_FLATSIZE, &newflatsize,
-
		PKG_NEW_PKGSIZE, &newpkgsize, PKG_LICENSE_LOGIC, &licenselogic, PKG_MESSAGE, &message);
-

-
	if (opt & INFO_RAW) {
-
		pkg_emit_manifest(pkg, &m);
-
		printf("%s\n", m);
-
		free(m);
-
	} else if (opt & INFO_FULL) {
-
		printf("%-15s: %s\n", "Name", name);
-
		printf("%-15s: %s\n", "Version", version);
-
		printf("%-15s: %s\n", "Origin", origin);
-
		printf("%-15s: %s\n", "Prefix", prefix);
-

-
		if ((pkg_type(pkg) == PKG_REMOTE) && multirepos_enabled)
-
			printf("%-15s: %s [%s]\n", "Repository", reponame, repourl);
-

-
                if (!pkg_list_is_empty(pkg, PKG_CATEGORIES)) {
-
                        printf("%-15s:", "Categories");
-
                        while (pkg_categories(pkg, &cat) == EPKG_OK)
-
                                printf(" %s", pkg_category_name(cat));
-
                        printf("\n");
-
                }
-

-
		if (!pkg_list_is_empty(pkg, PKG_LICENSES)) {
-
			printf("%-15s:", "Licenses");
-
			while (pkg_licenses(pkg, &lic) == EPKG_OK) {
-
				printf(" %s", pkg_license_name(lic));
-
				if (licenselogic != 1)
-
					printf(" %c", licenselogic);
-
				else
-
					printf(" ");
-
			}
-
			printf("\b \n");
+
	pkg_get(pkg,
+
		PKG_NAME,          &name,
+
		PKG_VERSION,       &version,
+
		PKG_PREFIX,        &prefix,
+
		PKG_ORIGIN,        &origin,
+
		PKG_REPONAME,      &reponame,
+
		PKG_REPOURL,       &repourl,
+
		PKG_MAINTAINER,    &maintainer,
+
		PKG_WWW,           &www,
+
		PKG_COMMENT,       &comment,
+
		PKG_DESC,          &desc,
+
		PKG_FLATSIZE,      &flatsize,
+
		PKG_NEW_FLATSIZE,  &newflatsize,
+
		PKG_NEW_PKGSIZE,   &newpkgsize,
+
		PKG_LICENSE_LOGIC, &licenselogic,
+
		PKG_MESSAGE,       &message,
+
		PKG_ARCH,	   &arch,
+
		PKG_REPOPATH,	   &repopath);
+

+
	if (!multirepos_enabled)
+
		pkg_config_string(PKG_CONFIG_REPO, &repourl);
+

+
	if (options & INFO_RAW) { /* Not for remote packages */
+
		if (pkg_type(pkg) != PKG_REMOTE) {
+
			pkg_emit_manifest(pkg, &m);
+
			printf("%s\n", m);
+
			free(m);
		}
+
		return;
+
	}

-
		printf("%-15s: %s\n", "Maintainer", maintainer);
-
		printf("%-15s: %s\n", "WWW", www);
-
		printf("%-15s: %s\n", "Comment", comment);
-

-
                if (!pkg_list_is_empty(pkg, PKG_OPTIONS)) {
-
                        printf("%-15s: \n", "Options");
-
                        while (pkg_options(pkg, &option) == EPKG_OK)
-
                                printf("\t%s: %s\n", pkg_option_opt(option), pkg_option_value(option));
-
                }
+
	if (!quiet) {
+
		/* Print a tag-line identifying the package -- either
+
		   NAMEVER, ORIGIN or NAME (in that order of
+
		   preference).  This may be the only output from this
+
		   function */
+

+
		if (options & INFO_TAG_NAMEVER)
+
			cout = printf("%s-%s", name, version);
+
		else if (options & INFO_TAG_ORIGIN)
+
			cout = printf("%s", origin);
+
		else if (options & INFO_TAG_NAME)
+
			cout = printf("%s", name);
+
	}

-
		if (!pkg_list_is_empty(pkg, PKG_SHLIBS)) {
-
			printf("%-15s:", "SharedLibraries");
-
			while (pkg_shlibs(pkg, &shlib) == EPKG_OK)
-
				printf(" %s", pkg_shlib_name(shlib));
-
			printf("\n");
-
		}
+
	/* If we printed a tag, and there are no other items to print,
+
	   then just return now. If there's only one single-line item
+
	   to print, show it at column 32 on the same line. If there's
+
	   one multi-line item to print, start a new line. If there is
+
	   more than one item to print per pkg, use 'key : value'
+
	   style to show on a new line.  */

-
		if (pkg_type(pkg) == PKG_INSTALLED || pkg_type(pkg) == PKG_FILE) {
-
			humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0);
-
			printf("%-15s: %s\n", "Flat size", size);
-
		} else {
-
			humanize_number(size, sizeof(size), newflatsize, "B", HN_AUTOSCALE, 0);
-
			printf("%-15s: %s\n", "Flat size", size);
-
			humanize_number(size, sizeof(size), newpkgsize, "B", HN_AUTOSCALE, 0);
-
			printf("%-15s: %s\n", "Pkg size", size);
-
		}
+
	info_num = 0;
+
	for (opt = 0x1; opt <= INFO_LASTFIELD; opt <<= 1) 
+
		if ((opt & options) != 0)
+
			info_num++;

-
		printf("%-15s: \n%s\n", "Description", desc);
+
	if (info_num == 0 && cout > 0) {
		printf("\n");
-
	} else if (opt & INFO_PRINT_DEP) {
-
		if (!(opt & INFO_QUIET))
-
			printf("%s-%s depends on:\n", name, version);
-

-
                while (pkg_deps(pkg, &dep) == EPKG_OK) {
-
                        printf("%s-%s\n", pkg_dep_name(dep), pkg_dep_version(dep));
-
                }
-

-
                if (!(opt & INFO_QUIET))
-
                        printf("\n");
-
	} else if (opt & INFO_PRINT_MESSAGE) {
-
		if (message)
-
			printf("%s", message);
-
	} else if (opt & INFO_PRINT_RDEP) {
-
		if (!(opt & INFO_QUIET))
-
			printf("%s-%s is required by:\n", name, version);
-

-
                while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
-
                        printf("%s-%s\n", pkg_dep_name(dep), pkg_dep_version(dep));
-
                }
-

-
                if (!(opt & INFO_QUIET))
-
                        printf("\n");
-
	} else if (opt & INFO_LIST_FILES) {
-
		if (!(opt & INFO_QUIET))
-
			printf("%s-%s owns the following files:\n", name, version);
-

-
                while (pkg_files(pkg, &file) == EPKG_OK) {
-
                        printf("%s\n", pkg_file_path(file));
-
                }
-

-
                if (!(opt & INFO_QUIET))
-
                        printf("\n");
-
	} else if (opt & INFO_LIST_SHLIBS) {
-
		if (!(opt & INFO_QUIET))
-
			printf("%s-%s uses the following shared libraries:\n", name, version);
-

-
                while (pkg_shlibs(pkg, &shlib) == EPKG_OK) {
-
                        printf("%s\n", pkg_shlib_name(shlib));
-
                }
-

-
                if (!(opt & INFO_QUIET))
-
                        printf("\n");
-
        } else if (opt & INFO_SIZE) {
-
		if (pkg_type(pkg) == PKG_INSTALLED) {
-
			humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0);
-
			printf("%s-%s size is: %s\n", name, version, size);
-
		} else {
-
			humanize_number(size, sizeof(size), newflatsize, "B", HN_AUTOSCALE, 0);
-
			printf("%s-%s flat size is: %s\n", name, version, size);
-
			humanize_number(size, sizeof(size), newpkgsize, "B", HN_AUTOSCALE, 0);
-
			printf("%s-%s package size is: %s\n", name, version, size);
+
		return;
+
	}
+

+
	if (info_num == 1) {
+
		/* Only one item to print */
+
		print_tag = false;
+
		if (!quiet) {
+
			if (options & INFO_MULTILINE)
+
				printf(":\n");
+
			else {
+
				if (cout < 31)
+
					cout = 31 - cout;
+
				else
+
					cout = 1;
+
				printf("%*s", cout, " ");
+
			}
		}
-
        } else if (opt & INFO_ORIGIN) {
-
                if (opt & INFO_QUIET)
-
                        printf("%s\n", origin);
-
                else
-
                        printf("%s-%s: %s\n", name, version, origin);
-
        } else if (opt & INFO_PREFIX) {
-
                if (opt & INFO_QUIET)
-
                        printf("%s\n", prefix);
-
                else
-
                        printf("%s-%s: %s\n", name, version, prefix);
-
        } else {
-
                if (opt & INFO_QUIET)
-
                        printf("%s-%s\n", name, version);
-
                else {
-
			snprintf(buf, BUFSIZ, "%s-%s", name, version);
-
			if ((pkg_type(pkg) == PKG_REMOTE) && multirepos_enabled)
-
				printf("%-30s [repository: %s]: %s\n", buf, reponame, comment);
+
	} else {
+
		/* Several items to print */
+
		print_tag = true;
+
		if (!quiet)
+
			printf("\n");
+
	}
+

+
	for (opt = 0x1; opt <= INFO_LASTFIELD; opt <<= 1) {
+
		if ((opt & options) == 0)
+
			continue;
+

+
		switch (opt) {
+
		case INFO_NAME:
+
			if (print_tag)
+
				printf("%-15s: ", "Name");
+
			printf("%s\n", name);
+
			break;
+
		case INFO_VERSION:
+
			if (print_tag)
+
				printf("%-15s: ", "Version");
+
			printf("%s\n", version);
+
			break;
+
		case INFO_ORIGIN:
+
			if (print_tag)
+
				printf("%-15s: ", "Origin");
+
			printf("%s\n", origin);
+
			break;
+
		case INFO_PREFIX:
+
			if (print_tag)
+
				printf("%-15s: ", "Prefix");
+
			printf("%s\n", prefix);
+
			break;
+
		case INFO_REPOSITORY:
+
			if (pkg_type(pkg) == PKG_REMOTE &&
+
			    repourl != NULL && repourl[0] != '\0') {
+
				if (print_tag)
+
					printf("%-15s: ", "Repository");
+
				printf("%s [%s]\n", reponame, repourl);
+
			} else if (!print_tag)
+
				printf("\n");
+
			break;
+
		case INFO_CATEGORIES:
+
			if (!pkg_list_is_empty(pkg, PKG_CATEGORIES)) {
+
				if (print_tag)
+
					printf("%-15s: ", "Categories");
+
				if (pkg_categories(pkg, &cat) == EPKG_OK)
+
					printf("%s", pkg_category_name(cat));
+
				while (pkg_categories(pkg, &cat) == EPKG_OK)
+
					printf(" %s", pkg_category_name(cat));
+
				printf("\n");
+
			} else if (!print_tag)
+
				printf("\n");
+
			break;
+
		case INFO_LICENSES:
+
			if (!pkg_list_is_empty(pkg, PKG_LICENSES)) {
+
				if (print_tag)
+
					printf("%-15s: ", "Licenses");
+
				if (pkg_licenses(pkg, &lic) == EPKG_OK)
+
					printf("%s", pkg_license_name(lic));
+
				while (pkg_licenses(pkg, &lic) == EPKG_OK) {
+
					if (licenselogic != 1)
+
						printf(" %c", licenselogic);
+
					printf(" %s", pkg_license_name(lic));
+
				}
+
				printf("\n");				
+
			} else if (!print_tag)
+
				printf("\n");
+
			break;
+
		case INFO_MAINTAINER:
+
			if (print_tag)
+
				printf("%-15s: ", "Maintainer");
+
			printf("%s\n", maintainer);
+
			break;
+
		case INFO_WWW:	
+
			if (print_tag)
+
				printf("%-15s: ", "WWW");
+
			printf("%s\n", www);
+
			break;
+
		case INFO_COMMENT:
+
			if (print_tag)
+
				printf("%-15s: ", "Comment");
+
			printf("%s\n", comment);
+
			break;
+
		case INFO_OPTIONS:
+
			if (!pkg_list_is_empty(pkg, PKG_OPTIONS)) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Options");
+
				while (pkg_options(pkg, &option) == EPKG_OK)
+
					printf("\t%-15s: %s\n",
+
					       pkg_option_opt(option),
+
					       pkg_option_value(option));
+
			}
+
			break;
+
		case INFO_SHLIBS:
+
			if (!pkg_list_is_empty(pkg, PKG_SHLIBS)) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Shared Libs");
+
				while (pkg_shlibs(pkg, &shlib) == EPKG_OK)
+
					printf("\t%s\n", pkg_shlib_name(shlib));
+
			}
+
			break;
+
		case INFO_FLATSIZE:
+
			if (pkg_type(pkg) == PKG_INSTALLED ||
+
			    pkg_type(pkg) == PKG_FILE)
+
				humanize_number(size, sizeof(size),
+
						flatsize,"B",
+
						HN_AUTOSCALE, 0);
			else
-
				printf("%-30s %s\n", buf, comment);
+
				humanize_number(size, sizeof(size),
+
						newflatsize,"B",
+
						HN_AUTOSCALE, 0);
+

+
			if (print_tag)
+
				printf("%-15s: ", "Flat size");
+
			printf("%s\n", size);
+
			break;
+
		case INFO_PKGSIZE: /* Remote pkgs only */
+
			if (pkg_type(pkg) == PKG_REMOTE) {
+
				humanize_number(size, sizeof(size),
+
						newpkgsize,"B",
+
						HN_AUTOSCALE, 0);
+
				if (print_tag)
+
					printf("%-15s: ", "Pkg size");
+
				printf("%s\n", size);
+
			} else if (!print_tag)
+
				printf("\n");
+
			break;
+
		case INFO_DESCR:
+
			if (print_tag)
+
				printf("%-15s:\n", "Description");
+
			printf("%s\n", desc);
+
			break;
+
		case INFO_MESSAGE:
+
			if (message) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Message");
+
				printf("%s\n", message);
+
			}
+
			break;
+
		case INFO_DEPS:
+
			if (!pkg_list_is_empty(pkg, PKG_DEPS)) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Depends on");
+
				while (pkg_deps(pkg, &dep) == EPKG_OK)
+
					printf("\t%s-%s\n",
+
					       pkg_dep_name(dep),
+
					       pkg_dep_version(dep));
+
			}
+
			break;
+
		case INFO_RDEPS:
+
			if (!pkg_list_is_empty(pkg, PKG_RDEPS)) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Required by");
+
				while (pkg_rdeps(pkg, &dep) == EPKG_OK)
+
					printf("\t%s-%s\n",
+
					       pkg_dep_name(dep),
+
					       pkg_dep_version(dep));
+
			}
+
			break;
+
		case INFO_FILES: /* Installed pkgs only */
+
			if (pkg_type(pkg) != PKG_REMOTE &&
+
			    !pkg_list_is_empty(pkg, PKG_FILES)) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Files");
+
				while (pkg_files(pkg, &file) == EPKG_OK)
+
					printf("\t%s\n",
+
					       pkg_file_path(file));
+
			}
+
			break;
+
		case INFO_DIRS:	/* Installed pkgs only */
+
			if (pkg_type(pkg) != PKG_REMOTE &&
+
			    !pkg_list_is_empty(pkg, PKG_DIRS)) {
+
				if (print_tag)
+
					printf("%-15s:\n", "Directories");
+
				while (pkg_dirs(pkg, &dir) == EPKG_OK)
+
					printf("\t%s\n",
+
					       pkg_dir_path(dir));
+
			}
+
			break;
+
		case INFO_USERS: /* Installed pkgs only */
+
			if (pkg_type(pkg) != PKG_REMOTE &&
+
			    !pkg_list_is_empty(pkg, PKG_USERS)) {
+
				if (print_tag)
+
					printf("%-15s: ", "Users");
+
				if (pkg_users(pkg, &user) == EPKG_OK)
+
					printf("%s", pkg_user_name(user));
+
				while (pkg_users(pkg, &user) == EPKG_OK)
+
					printf(" %s", pkg_user_name(user));
+
				printf("\n");
+
			}
+
			break;
+
		case INFO_GROUPS: /* Installed pkgs only */
+
			if (pkg_type(pkg) != PKG_REMOTE &&
+
			    !pkg_list_is_empty(pkg, PKG_GROUPS)) {
+
				if (print_tag)
+
					printf("%-15s: ", "Groups");
+
				if (pkg_groups(pkg, &group) == EPKG_OK)
+
					printf("%s", pkg_group_name(group));
+
				while (pkg_groups(pkg, &group) == EPKG_OK)
+
					printf(" %s", pkg_group_name(group));
+
				printf("\n");
+
			}
+
			break;
+
		case INFO_ARCH:
+
			if (print_tag)
+
				printf("%-15s: ", "Architecture");
+
			printf("%s\n", arch);
+
			break;
+
		case INFO_REPOURL:
+
			if (pkg_type(pkg) == PKG_REMOTE &&
+
			    repourl != NULL && repourl[0] != '\0') {
+
				if (print_tag)
+
					printf("%-15s: ", "Pkg URL");
+
				if (repourl[strlen(repourl) -1] == '/')
+
					printf("%s%s\n", repourl, repopath);
+
				else
+
					printf("%s/%s\n", repourl, repopath);
+
			} else if (!print_tag)
+
				printf("\n");
+
			break;
		}
-
        }
+
	}
}

void