xbps-query: added -S, --search-regex to match EREs against pkg props in repos.

This commit is contained in:
Juan RP 2014-05-25 11:03:31 +02:00
parent 1c26b2ef95
commit 1f0605810c
5 changed files with 94 additions and 23 deletions

11
NEWS
View File

@ -1,5 +1,16 @@
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).
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
...
$
* Imported portable proplib 0.6.4 from https://github.com/xtraeme/portableproplib.
* Fixed a new issue with virtual packages, if a pkg provides a virtual package

View File

@ -68,6 +68,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 *);
int repo_search(struct xbps_handle *, int, char **, const char *, bool);
#endif /* !_XBPS_QUERY_DEFS_H_ */

View File

@ -57,8 +57,9 @@ usage(bool fail)
" -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 PATTERN(s) Search for packages owning PATTERN(s)\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");
@ -69,7 +70,7 @@ usage(bool fail)
int
main(int argc, char **argv)
{
const char *shortopts = "C:c:D:dfhHLlmOop:Rr:sVvXx";
const char *shortopts = "C:c:D:dfhHLlmOop:Rr:sSVvXx";
const struct option longopts[] = {
{ "config", required_argument, NULL, 'C' },
{ "cachedir", required_argument, NULL, 'c' },
@ -85,6 +86,7 @@ main(int argc, char **argv)
{ "repository", optional_argument, NULL, 'R' },
{ "rootdir", required_argument, NULL, 'r' },
{ "search", no_argument, NULL, 's' },
{ "search-regex", no_argument, NULL, 'S' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ "files", no_argument, NULL, 'f' },
@ -97,13 +99,13 @@ main(int argc, char **argv)
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, repo_mode, opmode, fulldeptree;
bool show, search, search_regex, repo_mode, opmode, fulldeptree;
rootdir = cachedir = conffile = props = NULL;
flags = rv = c = 0;
list_pkgs = list_repos = list_hold = orphans = search = own = false;
list_manual = show_prop = show_files = false;
show = show_rdeps = fulldeptree = false;
search_regex = show = show_rdeps = fulldeptree = false;
repo_mode = opmode = false;
memset(&xh, 0, sizeof(xh));
@ -164,6 +166,9 @@ main(int argc, char **argv)
case 's':
search = opmode = true;
break;
case 'S':
search_regex = opmode = true;
break;
case 'v':
flags |= XBPS_FLAG_VERBOSE;
break;
@ -232,9 +237,9 @@ main(int argc, char **argv)
else
rv = ownedby(&xh, argc - optind, argv + optind);
} else if (search) {
} else if (search || search_regex) {
/* search mode */
rv = repo_search(&xh, argc - optind, argv + optind, props);
rv = repo_search(&xh, argc - optind, argv + optind, props, search_regex);
} else if (show || show_prop) {
/* show mode */

View File

@ -38,11 +38,13 @@
#include <libgen.h>
#include <fnmatch.h>
#include <assert.h>
#include <regex.h>
#include <xbps.h>
#include "defs.h"
struct search_data {
bool regex;
int npatterns;
int maxcols;
char **patterns;
@ -117,11 +119,23 @@ search_array_cb(struct xbps_handle *xhp _unused,
if (xbps_match_virtual_pkg_in_dict(obj, sd->patterns[x]))
vpkgfound = true;
if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) ||
(strcasestr(pkgver, sd->patterns[x])) ||
(strcasestr(desc, sd->patterns[x])) || vpkgfound) {
xbps_array_add_cstring_nocopy(sd->results, pkgver);
xbps_array_add_cstring_nocopy(sd->results, desc);
if (sd->regex) {
regex_t regex;
regmatch_t regmatches[1];
regcomp(&regex, sd->patterns[x], REG_EXTENDED);
if ((regexec(&regex, pkgver, 1, regmatches, REG_EXTENDED) == 0) ||
(regexec(&regex, desc, 1, regmatches, REG_EXTENDED) == 0)) {
xbps_array_add_cstring_nocopy(sd->results, pkgver);
xbps_array_add_cstring_nocopy(sd->results, desc);
}
} else {
if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) ||
(strcasestr(pkgver, sd->patterns[x])) ||
(strcasestr(desc, sd->patterns[x])) || vpkgfound) {
xbps_array_add_cstring_nocopy(sd->results, pkgver);
xbps_array_add_cstring_nocopy(sd->results, desc);
}
}
}
return 0;
@ -133,11 +147,21 @@ search_array_cb(struct xbps_handle *xhp _unused,
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 ((strcasestr(str, sd->patterns[x])) ||
(fnmatch(sd->patterns[x], str, FNM_PERIOD)) == 0) {
xbps_dictionary_get_cstring_nocopy(obj,
"pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
if (sd->regex) {
regex_t regex;
regmatch_t regmatches[1];
regcomp(&regex, sd->patterns[x], REG_EXTENDED);
if (regexec(&regex, str, 1, regmatches, 0) == 0) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
} else {
if ((strcasestr(str, sd->patterns[x])) ||
(fnmatch(sd->patterns[x], str, FNM_PERIOD)) == 0) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
}
}
}
@ -149,10 +173,20 @@ search_array_cb(struct xbps_handle *xhp _unused,
/* property is a string */
str = xbps_string_cstring_nocopy(obj2);
for (x = 0; x < sd->npatterns; x++) {
if (strcasestr(str, sd->patterns[x])) {
xbps_dictionary_get_cstring_nocopy(obj,
"pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
if (sd->regex) {
regex_t regex;
regmatch_t regmatches[1];
regcomp(&regex, sd->patterns[x], REG_EXTENDED);
if (regexec(&regex, str, 1, regmatches, 0) == 0) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
} else {
if (strcasestr(str, sd->patterns[x])) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
}
}
}
}
@ -174,11 +208,12 @@ 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)
repo_search(struct xbps_handle *xhp, int npatterns, char **patterns, const char *prop, bool regex)
{
struct search_data sd;
int rv;
sd.regex = regex;
sd.prop = prop;
sd.npatterns = npatterns;
sd.patterns = patterns;

View File

@ -1,4 +1,4 @@
.Dd April 21, 2014
.Dd May 25, 2014
.Os Void Linux
.Dt xbps-query 8
.Sh NAME
@ -133,6 +133,26 @@ The
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
.Ar PATTERN