xbps-query: added --regex to use EREs in ownedby and search modes.

This replaces previous -S, --search-regex option. The regex option
can now be used in the ownedby and search modes.

Also added -S, --show option which is the default mode if no other
mode set, and defaults to it to preserve compatibility.
This commit is contained in:
Juan RP 2014-05-26 17:30:44 +02:00
parent 0fbab93383
commit 0eadaab19d
6 changed files with 163 additions and 180 deletions

11
NEWS
View File

@ -1,13 +1,18 @@
xbps-0.37 (???):
* xbps-query(8): new option "-S, --search-regex" that matches packages in
repositories with Extended Regular Expressions as explained in regex(7).
* xbps-query(8): new option (-S, --show) which shows info of a package
installed locally or in a repository with -R. This is the default mode
if no other mode is set; to preserve compatibility with previous versions.
* xbps-query(8): new long option "--regex" that can be used in the
"ownedby (-o, --ownedby)" and "search (-s, --search)" modes to match
Extended Regular Expressions against package properties.
This allows you to find packages by matching EREs in package properties,
for example to find out what packages were built between 2014-05-23 and
2014-05-25:
$ xbps-query -S 2014-05-2[35] -p build-date
$ xbps-query --regex -s 2014-05-2[35] -p build-date
...
$

View File

@ -53,8 +53,7 @@ int repo_show_pkg_namedesc(struct xbps_handle *, xbps_object_t, void *,
bool *);
/* from ownedby.c */
int ownedby(struct xbps_handle *, int, char **);
int repo_ownedby(struct xbps_handle *, int, char **);
int ownedby(struct xbps_handle *, const char *, bool, bool);
/* From list.c */
unsigned int find_longest_pkgver(struct xbps_handle *, xbps_object_t);
@ -68,6 +67,6 @@ int list_pkgs_pkgdb(struct xbps_handle *);
int repo_list(struct xbps_handle *);
/* from search.c */
int repo_search(struct xbps_handle *, int, char **, const char *, bool);
int repo_search(struct xbps_handle *, const char *, const char *, bool);
#endif /* !_XBPS_QUERY_DEFS_H_ */

View File

@ -36,33 +36,34 @@ static void __attribute__((noreturn))
usage(bool fail)
{
fprintf(stdout,
"Usage: xbps-query [OPTIONS...] [PKGNAME]\n"
"Usage: xbps-query [OPTIONS] MODE [ARGUMENTS]\n"
"\nOPTIONS\n"
" -C --config <file> Full path to configuration file\n"
" -c --cachedir <dir> Full path to cachedir\n"
" -d --debug Debug mode shown to stderr\n"
" -h --help Print help usage\n"
" -p --property PROP,... Show properties for PKGNAME\n"
" -p --property PROP[,...] Show properties for PKGNAME\n"
" -R --repository Enable repository mode. This mode explicitly\n"
" looks for packages in repositories.\n"
" --repository=<url> Enable repository mode and add repository\n"
" to the top of the list. This option can be\n"
" specified multiple times.\n"
" --regex Use Extended Regular Expressions to match\n"
" -r --rootdir <dir> Full path to rootdir\n"
" -V --version Show XBPS version\n"
" -v --verbose Verbose messages\n"
"\nMODE [only one mode may be specified]\n"
" -l --list-pkgs List available packages\n"
" -L --list-repos List working repositories\n"
"\nMODE\n"
" -l --list-pkgs List installed packages\n"
" -L --list-repos List registered repositories\n"
" -H --list-hold-pkgs List packages on hold state\n"
" -m --list-manual-pkgs List packages installed explicitly\n"
" -O --list-orphans List package orphans\n"
" -o --ownedby FILE(s) Search for packages owning FILE(s)\n"
" -s --search PATTERN(s) Search for packages matching PATTERN(s)\n"
" -S,--search-regex RE Search for packages matching RE\n"
" -f --files Show files for PKGNAME\n"
" -x --deps Show dependencies for PKGNAME (set it twice for a full dependency tree)\n"
" -X --revdeps Show reverse dependencies for PKGNAME\n");
" -o --ownedby FILE Search for package files by matching STRING or REGEX\n"
" -S --show PKG Show information for PKG [default mode]\n"
" -s --search PKG Search for packages by matching PKG, STRING or REGEX\n"
" -f --files PKG Show package files for PKG\n"
" -x --deps PKG Show dependencies for PKG (set it twice for a full dependency tree)\n"
" -X --revdeps PKG Show reverse dependencies for PKG\n");
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
@ -70,7 +71,7 @@ usage(bool fail)
int
main(int argc, char **argv)
{
const char *shortopts = "C:c:D:dfhHLlmOop:Rr:sSVvXx";
const char *shortopts = "C:c:D:dfhHLlmOo:p:Rr:s:S:VvXx";
const struct option longopts[] = {
{ "config", required_argument, NULL, 'C' },
{ "cachedir", required_argument, NULL, 'c' },
@ -81,31 +82,32 @@ main(int argc, char **argv)
{ "list-hold-pkgs", no_argument, NULL, 'H' },
{ "list-manual-pkgs", no_argument, NULL, 'm' },
{ "list-orphans", no_argument, NULL, 'O' },
{ "ownedby", no_argument, NULL, 'o' },
{ "ownedby", required_argument, NULL, 'o' },
{ "property", required_argument, NULL, 'p' },
{ "repository", optional_argument, NULL, 'R' },
{ "regex", no_argument, NULL, 0 },
{ "rootdir", required_argument, NULL, 'r' },
{ "search", no_argument, NULL, 's' },
{ "search-regex", no_argument, NULL, 'S' },
{ "show", required_argument, NULL, 'S' },
{ "search", required_argument, NULL, 's' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ "files", no_argument, NULL, 'f' },
{ "deps", no_argument, NULL, 'x' },
{ "revdeps", no_argument, NULL, 'X' },
{ "files", required_argument, NULL, 'f' },
{ "deps", required_argument, NULL, 'x' },
{ "revdeps", required_argument, NULL, 'X' },
{ NULL, 0, NULL, 0 },
};
struct xbps_handle xh;
const char *rootdir, *cachedir, *conffile, *props;
const char *pkg, *rootdir, *cachedir, *conffile, *props;
int c, flags, rv, show_deps = 0;
bool list_pkgs, list_repos, orphans, own;
bool list_manual, list_hold, show_prop, show_files, show_rdeps;
bool show, search, search_regex, repo_mode, opmode, fulldeptree;
bool show, search, regex, repo_mode, opmode, fulldeptree;
rootdir = cachedir = conffile = props = NULL;
rootdir = cachedir = conffile = props = pkg = NULL;
flags = rv = c = 0;
list_pkgs = list_repos = list_hold = orphans = search = own = false;
list_manual = show_prop = show_files = false;
search_regex = show = show_rdeps = fulldeptree = false;
regex = show = show_rdeps = fulldeptree = false;
repo_mode = opmode = false;
memset(&xh, 0, sizeof(xh));
@ -124,6 +126,7 @@ main(int argc, char **argv)
flags |= XBPS_FLAG_DEBUG;
break;
case 'f':
pkg = optarg;
show_files = opmode = true;
break;
case 'H':
@ -145,6 +148,7 @@ main(int argc, char **argv)
orphans = true;
break;
case 'o':
pkg = optarg;
own = opmode = true;
break;
case 'p':
@ -163,11 +167,13 @@ main(int argc, char **argv)
case 'r':
rootdir = optarg;
break;
case 's':
search = opmode = true;
break;
case 'S':
search_regex = opmode = true;
pkg = optarg;
show = opmode = true;
break;
case 's':
pkg = optarg;
search = opmode = true;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
@ -176,24 +182,32 @@ main(int argc, char **argv)
printf("%s\n", XBPS_RELVER);
exit(EXIT_SUCCESS);
case 'x':
pkg = optarg;
show_deps++;
opmode = true;
break;
case 'X':
pkg = optarg;
show_rdeps = opmode = true;
break;
case 0:
regex = true;
break;
case '?':
usage(true);
/* NOTREACHED */
}
}
if (!opmode && argc > optind)
show = true;
else if (argc == 1 || (opmode && (argc == optind)))
usage(true);
else if ((search || own) && (argc == optind))
usage(true);
argc -= optind;
argv += optind;
if (argc > 1)
usage(true);
else if (!opmode) {
/* show mode by default */
show = opmode = true;
pkg = *argv;
}
/*
* Initialize libxbps.
*/
@ -232,29 +246,25 @@ main(int argc, char **argv)
} else if (own) {
/* ownedby mode */
if (repo_mode)
rv = repo_ownedby(&xh, argc - optind, argv + optind);
else
rv = ownedby(&xh, argc - optind, argv + optind);
rv = ownedby(&xh, pkg, repo_mode, regex);
} else if (search || search_regex) {
} else if (search) {
/* search mode */
rv = repo_search(&xh, argc - optind, argv + optind, props, search_regex);
rv = repo_search(&xh, pkg, props, regex);
} else if (show || show_prop) {
/* show mode */
if (repo_mode)
rv = repo_show_pkg_info(&xh, argv[optind], props);
rv = repo_show_pkg_info(&xh, pkg, props);
else
rv = show_pkg_info_from_metadir(&xh,
argv[optind], props);
rv = show_pkg_info_from_metadir(&xh, pkg, props);
} else if (show_files) {
/* show-files mode */
if (repo_mode)
rv = repo_show_pkg_files(&xh, argv[optind]);
rv = repo_show_pkg_files(&xh, pkg);
else
rv = show_pkg_files_from_metadir(&xh, argv[optind]);
rv = show_pkg_files_from_metadir(&xh, pkg);
} else if (show_deps) {
/* show-deps mode */
@ -262,16 +272,16 @@ main(int argc, char **argv)
fulldeptree = true;
if (repo_mode)
rv = repo_show_pkg_deps(&xh, argv[optind], fulldeptree);
rv = repo_show_pkg_deps(&xh, pkg, fulldeptree);
else
rv = show_pkg_deps(&xh, argv[optind], fulldeptree);
rv = show_pkg_deps(&xh, pkg, fulldeptree);
} else if (show_rdeps) {
/* show-rdeps mode */
if (repo_mode)
rv = repo_show_pkg_revdeps(&xh, argv[optind]);
rv = repo_show_pkg_revdeps(&xh, pkg);
else
rv = show_pkg_revdeps(&xh, argv[optind]);
rv = show_pkg_revdeps(&xh, pkg);
}
exit(rv);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2010-2013 Juan Romero Pardines.
* Copyright (c) 2010-2014 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,14 +31,14 @@
#include <fnmatch.h>
#include <dirent.h>
#include <assert.h>
#include <regex.h>
#include <xbps.h>
#include "defs.h"
struct ffdata {
int npatterns;
char **patterns;
const char *repouri;
bool regex;
const char *pat, *repouri;
xbps_array_t allkeys;
xbps_dictionary_t filesd;
};
@ -52,7 +52,7 @@ match_files_by_pattern(xbps_dictionary_t pkg_filesd,
xbps_array_t array;
xbps_object_t obj;
const char *keyname, *filestr, *typestr;
int x;
regex_t regex;
keyname = xbps_dictionary_keysym_cstring_nocopy(key);
@ -72,11 +72,15 @@ match_files_by_pattern(xbps_dictionary_t pkg_filesd,
xbps_dictionary_get_cstring_nocopy(obj, "file", &filestr);
if (filestr == NULL)
continue;
for (x = 0; x < ffd->npatterns; x++) {
if ((fnmatch(ffd->patterns[x], filestr, FNM_PERIOD)) == 0) {
printf("%s: %s (%s)\n", pkgver,
filestr, typestr);
if (ffd->regex) {
regcomp(&regex, ffd->pat, REG_EXTENDED|REG_NOSUB);
if (regexec(&regex, filestr, 0, 0, 0) == 0) {
printf("%s: %s (%s)\n", pkgver, filestr, typestr);
}
regfree(&regex);
} else {
if ((fnmatch(ffd->pat, filestr, FNM_PERIOD)) == 0)
printf("%s: %s (%s)\n", pkgver, filestr, typestr);
}
}
}
@ -112,22 +116,6 @@ ownedby_pkgdb_cb(struct xbps_handle *xhp,
return 0;
}
int
ownedby(struct xbps_handle *xhp, int npatterns, char **patterns)
{
struct ffdata ffd;
char *rfile;
ffd.npatterns = npatterns;
ffd.patterns = patterns;
for (int i = 0; i < npatterns; i++) {
rfile = realpath(patterns[i], NULL);
if (rfile)
patterns[i] = rfile;
}
return xbps_pkgdb_foreach_cb(xhp, ownedby_pkgdb_cb, &ffd);
}
static int
repo_match_cb(struct xbps_handle *xhp _unused,
@ -138,14 +126,19 @@ repo_match_cb(struct xbps_handle *xhp _unused,
{
struct ffdata *ffd = arg;
const char *filestr;
regex_t regex;
for (unsigned int i = 0; i < xbps_array_count(obj); i++) {
xbps_array_get_cstring_nocopy(obj, i, &filestr);
for (int x = 0; x < ffd->npatterns; x++) {
if ((fnmatch(ffd->patterns[x], filestr, FNM_PERIOD)) == 0) {
printf("%s: %s (%s)\n",
key, filestr, ffd->repouri);
if (ffd->regex) {
regcomp(&regex, ffd->pat, REG_EXTENDED|REG_NOSUB);
if (regexec(&regex, filestr, 0, 0, 0) == 0) {
printf("%s: %s (%s)\n", key, filestr, ffd->repouri);
}
regfree(&regex);
} else {
if ((fnmatch(ffd->pat, filestr, FNM_PERIOD)) == 0)
printf("%s: %s (%s)\n", key, filestr, ffd->repouri);
}
}
@ -172,21 +165,22 @@ repo_ownedby_cb(struct xbps_repo *repo, void *arg, bool *done _unused)
}
int
repo_ownedby(struct xbps_handle *xhp, int npatterns, char **patterns)
ownedby(struct xbps_handle *xhp, const char *pat, bool repo, bool regex)
{
struct ffdata ffd;
char *rfile;
int rv;
ffd.npatterns = npatterns;
ffd.patterns = patterns;
ffd.regex = regex;
ffd.pat = pat;
for (int i = 0; i < npatterns; i++) {
rfile = realpath(patterns[i], NULL);
if (rfile)
patterns[i] = rfile;
}
if ((rfile = realpath(pat, NULL)) != NULL)
ffd.pat = rfile;
if (repo)
rv = xbps_rpool_foreach(xhp, repo_ownedby_cb, &ffd);
else
rv = xbps_pkgdb_foreach_cb(xhp, ownedby_pkgdb_cb, &ffd);
return rv;
}

View File

@ -45,10 +45,8 @@
struct search_data {
bool regex;
int npatterns;
int maxcols;
char **patterns;
const char *prop, *repourl;
const char *pat, *prop, *repourl;
xbps_array_t results;
};
@ -106,23 +104,19 @@ search_array_cb(struct xbps_handle *xhp _unused,
xbps_object_t obj2;
struct search_data *sd = arg;
const char *pkgver, *desc, *str;
int x;
regex_t regex;
if (sd->prop == NULL) {
bool vpkgfound = false;
/* no prop set, match on pkgver/short_desc objects */
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
xbps_dictionary_get_cstring_nocopy(obj, "short_desc", &desc);
for (x = 0; x < sd->npatterns; x++) {
bool vpkgfound = false;
if (xbps_match_virtual_pkg_in_dict(obj, sd->patterns[x]))
if (xbps_match_virtual_pkg_in_dict(obj, sd->pat))
vpkgfound = true;
if (sd->regex) {
regex_t regex;
regcomp(&regex, sd->patterns[x], REG_EXTENDED|REG_NOSUB);
regcomp(&regex, sd->pat, REG_EXTENDED|REG_NOSUB);
if ((regexec(&regex, pkgver, 0, 0, 0) == 0) ||
(regexec(&regex, desc, 0, 0, 0) == 0)) {
xbps_array_add_cstring_nocopy(sd->results, pkgver);
@ -130,14 +124,13 @@ search_array_cb(struct xbps_handle *xhp _unused,
}
regfree(&regex);
} else {
if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) ||
(strcasestr(pkgver, sd->patterns[x])) ||
(strcasestr(desc, sd->patterns[x])) || vpkgfound) {
if ((xbps_pkgpattern_match(pkgver, sd->pat)) ||
(strcasestr(pkgver, sd->pat)) ||
(strcasestr(desc, sd->pat)) || vpkgfound) {
xbps_array_add_cstring_nocopy(sd->results, pkgver);
xbps_array_add_cstring_nocopy(sd->results, desc);
}
}
}
return 0;
}
/* prop set, match on prop object instead */
@ -146,25 +139,21 @@ search_array_cb(struct xbps_handle *xhp _unused,
/* property is an array */
for (unsigned int i = 0; i < xbps_array_count(obj2); i++) {
xbps_array_get_cstring_nocopy(obj2, i, &str);
for (x = 0; x < sd->npatterns; x++) {
if (sd->regex) {
regex_t regex;
regcomp(&regex, sd->patterns[x], REG_EXTENDED|REG_NOSUB);
regcomp(&regex, sd->pat, REG_EXTENDED|REG_NOSUB);
if (regexec(&regex, str, 0, 0, 0) == 0) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
regfree(&regex);
} else {
if ((strcasestr(str, sd->patterns[x])) ||
(fnmatch(sd->patterns[x], str, FNM_PERIOD)) == 0) {
if ((strcasestr(str, sd->pat)) ||
(fnmatch(sd->pat, str, FNM_PERIOD)) == 0) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
}
}
}
} else if (xbps_object_type(obj2) == XBPS_TYPE_BOOL) {
/* property is a bool */
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
@ -172,24 +161,20 @@ search_array_cb(struct xbps_handle *xhp _unused,
} else if (xbps_object_type(obj2) == XBPS_TYPE_STRING) {
/* property is a string */
str = xbps_string_cstring_nocopy(obj2);
for (x = 0; x < sd->npatterns; x++) {
if (sd->regex) {
regex_t regex;
regcomp(&regex, sd->patterns[x], REG_EXTENDED|REG_NOSUB);
regcomp(&regex, sd->pat, REG_EXTENDED|REG_NOSUB);
if (regexec(&regex, str, 0, 0, 0) == 0) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
regfree(&regex);
} else {
if (strcasestr(str, sd->patterns[x])) {
if (strcasestr(str, sd->pat)) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
}
}
}
return 0;
}
@ -208,15 +193,14 @@ search_pkgs_cb(struct xbps_repo *repo, void *arg, bool *done _unused)
}
int
repo_search(struct xbps_handle *xhp, int npatterns, char **patterns, const char *prop, bool regex)
repo_search(struct xbps_handle *xhp, const char *pat, const char *prop, bool regex)
{
struct search_data sd;
int rv;
sd.regex = regex;
sd.pat = pat;
sd.prop = prop;
sd.npatterns = npatterns;
sd.patterns = patterns;
sd.maxcols = get_maxcols();
sd.results = xbps_array_create();

View File

@ -1,4 +1,4 @@
.Dd May 25, 2014
.Dd May 26, 2014
.Os Void Linux
.Dt xbps-query 8
.Sh NAME
@ -8,7 +8,7 @@
.Nm xbps-query
.Op OPTIONS
.Ar MODE
.Op PKG
.Op ARGUMENTS
.Sh DESCRIPTION
The
.Nm
@ -70,6 +70,13 @@ than looking in the target root directory. The
.Ar url
argument is optional and can be used to add the repository to the top of the list.
This option can be specified multiple times.
.It Fl -regex
Enables string matching by using Extended Regular Expressions in compatible modes,
currently in the
.Sy ownedby
and
.Sy search
modes.
.It Fl r, Fl -rootdir Ar dir
Specifies a full path for the target root directory.
.It Fl v, Fl -verbose
@ -125,36 +132,20 @@ manually by the user (i.e not as dependency of any package).
Lists package orphans in the package database (pkgdb), i.e packages that
were installed as dependencies and no package is currently depending on them
directly.
.It Fl o, Fl -ownedby Ar PATTERN...
Search for packages owning the files specified by
.It Fl o, Fl -ownedby Ar PATTERN
Search for package files by matching
.Ar PATTERN .
The
.Ar PATTERN
argument can be a simple string or a shell wildcard pattern as explained in
.Xr fnmatch 3 .
Multiple patterns may be specified.
.It Fl S, Fl -search-regex Ar RE.. [ Fl -property Ar PROP ]
Search for packages in repositories matching
.Ar RE
on its
.Em pkgver
and/or
.Em short_desc
properties.
.Ar RE
is a
.Em POSIX Extended Regular Expression
as explained in
.Xr regex 7 .
If a package property is specified with
.Fl -property,
all packages matching
.Ar RE
against
.Ar PROP
will be shown.
.It Fl s, Fl -search Ar PATTERN... [ Fl -property Ar PROP ]
Search for packages in repositories matching
argument can be a simple string, a shell wildcard pattern as explained in
.Xr fnmatch 3
or an Extended Regular Expression as explained in
.Xr regex 7
(if
.Fl -regex
option is set).
.It Fl s, Fl -search Ar PATTERN [ Fl -property Ar PROP ]
Search for packages in repositories by matching
.Ar PATTERN
on its
.Em pkgver