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-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. * 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 * 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 *); int repo_list(struct xbps_handle *);
/* from search.c */ /* 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_ */ #endif /* !_XBPS_QUERY_DEFS_H_ */

View File

@ -57,8 +57,9 @@ usage(bool fail)
" -H --list-hold-pkgs List packages on hold state\n" " -H --list-hold-pkgs List packages on hold state\n"
" -m --list-manual-pkgs List packages installed explicitly\n" " -m --list-manual-pkgs List packages installed explicitly\n"
" -O --list-orphans List package orphans\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 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" " -f --files Show files for PKGNAME\n"
" -x --deps Show dependencies for PKGNAME (set it twice for a full dependency tree)\n" " -x --deps Show dependencies for PKGNAME (set it twice for a full dependency tree)\n"
" -X --revdeps Show reverse dependencies for PKGNAME\n"); " -X --revdeps Show reverse dependencies for PKGNAME\n");
@ -69,7 +70,7 @@ usage(bool fail)
int int
main(int argc, char **argv) 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[] = { const struct option longopts[] = {
{ "config", required_argument, NULL, 'C' }, { "config", required_argument, NULL, 'C' },
{ "cachedir", required_argument, NULL, 'c' }, { "cachedir", required_argument, NULL, 'c' },
@ -85,6 +86,7 @@ main(int argc, char **argv)
{ "repository", optional_argument, NULL, 'R' }, { "repository", optional_argument, NULL, 'R' },
{ "rootdir", required_argument, NULL, 'r' }, { "rootdir", required_argument, NULL, 'r' },
{ "search", no_argument, NULL, 's' }, { "search", no_argument, NULL, 's' },
{ "search-regex", no_argument, NULL, 'S' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ "files", no_argument, NULL, 'f' }, { "files", no_argument, NULL, 'f' },
@ -97,13 +99,13 @@ main(int argc, char **argv)
int c, flags, rv, show_deps = 0; int c, flags, rv, show_deps = 0;
bool list_pkgs, list_repos, orphans, own; bool list_pkgs, list_repos, orphans, own;
bool list_manual, list_hold, show_prop, show_files, show_rdeps; 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; rootdir = cachedir = conffile = props = NULL;
flags = rv = c = 0; flags = rv = c = 0;
list_pkgs = list_repos = list_hold = orphans = search = own = false; list_pkgs = list_repos = list_hold = orphans = search = own = false;
list_manual = show_prop = show_files = false; list_manual = show_prop = show_files = false;
show = show_rdeps = fulldeptree = false; search_regex = show = show_rdeps = fulldeptree = false;
repo_mode = opmode = false; repo_mode = opmode = false;
memset(&xh, 0, sizeof(xh)); memset(&xh, 0, sizeof(xh));
@ -164,6 +166,9 @@ main(int argc, char **argv)
case 's': case 's':
search = opmode = true; search = opmode = true;
break; break;
case 'S':
search_regex = opmode = true;
break;
case 'v': case 'v':
flags |= XBPS_FLAG_VERBOSE; flags |= XBPS_FLAG_VERBOSE;
break; break;
@ -232,9 +237,9 @@ main(int argc, char **argv)
else else
rv = ownedby(&xh, argc - optind, argv + optind); rv = ownedby(&xh, argc - optind, argv + optind);
} else if (search) { } else if (search || search_regex) {
/* search mode */ /* 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) { } else if (show || show_prop) {
/* show mode */ /* show mode */

View File

@ -38,11 +38,13 @@
#include <libgen.h> #include <libgen.h>
#include <fnmatch.h> #include <fnmatch.h>
#include <assert.h> #include <assert.h>
#include <regex.h>
#include <xbps.h> #include <xbps.h>
#include "defs.h" #include "defs.h"
struct search_data { struct search_data {
bool regex;
int npatterns; int npatterns;
int maxcols; int maxcols;
char **patterns; 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])) if (xbps_match_virtual_pkg_in_dict(obj, sd->patterns[x]))
vpkgfound = true; vpkgfound = true;
if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) || if (sd->regex) {
(strcasestr(pkgver, sd->patterns[x])) || regex_t regex;
(strcasestr(desc, sd->patterns[x])) || vpkgfound) { regmatch_t regmatches[1];
xbps_array_add_cstring_nocopy(sd->results, pkgver);
xbps_array_add_cstring_nocopy(sd->results, desc); 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; 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++) { for (unsigned int i = 0; i < xbps_array_count(obj2); i++) {
xbps_array_get_cstring_nocopy(obj2, i, &str); xbps_array_get_cstring_nocopy(obj2, i, &str);
for (x = 0; x < sd->npatterns; x++) { for (x = 0; x < sd->npatterns; x++) {
if ((strcasestr(str, sd->patterns[x])) || if (sd->regex) {
(fnmatch(sd->patterns[x], str, FNM_PERIOD)) == 0) { regex_t regex;
xbps_dictionary_get_cstring_nocopy(obj, regmatch_t regmatches[1];
"pkgver", &pkgver);
printf("%s: %s (%s)\n", pkgver, str, sd->repourl); 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 */ /* property is a string */
str = xbps_string_cstring_nocopy(obj2); str = xbps_string_cstring_nocopy(obj2);
for (x = 0; x < sd->npatterns; x++) { for (x = 0; x < sd->npatterns; x++) {
if (strcasestr(str, sd->patterns[x])) { if (sd->regex) {
xbps_dictionary_get_cstring_nocopy(obj, regex_t regex;
"pkgver", &pkgver); regmatch_t regmatches[1];
printf("%s: %s (%s)\n", pkgver, str, sd->repourl);
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 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; struct search_data sd;
int rv; int rv;
sd.regex = regex;
sd.prop = prop; sd.prop = prop;
sd.npatterns = npatterns; sd.npatterns = npatterns;
sd.patterns = patterns; sd.patterns = patterns;

View File

@ -1,4 +1,4 @@
.Dd April 21, 2014 .Dd May 25, 2014
.Os Void Linux .Os Void Linux
.Dt xbps-query 8 .Dt xbps-query 8
.Sh NAME .Sh NAME
@ -133,6 +133,26 @@ The
argument can be a simple string or a shell wildcard pattern as explained in argument can be a simple string or a shell wildcard pattern as explained in
.Xr fnmatch 3 . .Xr fnmatch 3 .
Multiple patterns may be specified. 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 ] .It Fl s, Fl -search Ar PATTERN... [ Fl -property Ar PROP ]
Search for packages in repositories matching Search for packages in repositories matching
.Ar PATTERN .Ar PATTERN