public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-03-07 18:20 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-03-07 18:20 UTC (permalink / raw
  To: gentoo-commits

commit:     9ae56f85211d2c7c00b77b836e797339fc76f9b8
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Thu Mar  7 18:18:47 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Thu Mar  7 18:18:47 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=9ae56f85

qlist: change -U to display disabled flags with -v

reimplement umapstr() to allow printing flags not enabled, this is
slightly related to bug #656550.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qlist.optdesc.yaml |   2 +-
 man/qlist.1                    |   4 +-
 qlist.c                        | 183 ++++++++++++++++++++++++++---------------
 3 files changed, 119 insertions(+), 70 deletions(-)

diff --git a/man/include/qlist.optdesc.yaml b/man/include/qlist.optdesc.yaml
index a60ef0d..2b9299c 100644
--- a/man/include/qlist.optdesc.yaml
+++ b/man/include/qlist.optdesc.yaml
@@ -19,6 +19,6 @@ verbose: |
     When listing the package contents, a single \fB\-v\fR displays
     symlinks with an arrow (\->) to their target.  Two or more \fB\-v\fR
     adds colour to the entries and prints like \fB\-I\fR before the
-    listing.
+    listing.  Shows disabled USE-flags when used with \fB\-U\fR.
 quiet: |
     Suppresses the parenthesis around the USE-flags when used with \fB\-U\fR.

diff --git a/man/qlist.1 b/man/qlist.1
index c2c585c..4df7dab 100644
--- a/man/qlist.1
+++ b/man/qlist.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH qlist "1" "Feb 2019" "Gentoo Foundation" "qlist"
+.TH qlist "1" "Mar 2019" "Gentoo Foundation" "qlist"
 .SH NAME
 qlist \- list files owned by pkgname
 .SH SYNOPSIS
@@ -60,7 +60,7 @@ When used with \fB\-I\fR, print the package version next to name.
 When listing the package contents, a single \fB\-v\fR displays
 symlinks with an arrow (\->) to their target.  Two or more \fB\-v\fR
 adds colour to the entries and prints like \fB\-I\fR before the
-listing.
+listing.  Shows disabled USE-flags when used with \fB\-U\fR.
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
 Suppresses the parenthesis around the USE-flags when used with \fB\-U\fR.

diff --git a/qlist.c b/qlist.c
index 4a3b95a..3ca3f5e 100644
--- a/qlist.c
+++ b/qlist.c
@@ -43,84 +43,124 @@ static const char * const qlist_opts_help[] = {
 };
 #define qlist_usage(ret) usage(ret, QLIST_FLAGS, qlist_long_opts, qlist_opts_help, NULL, lookup_applet_idx("qlist"))
 
-static char *
-grab_pkg_umap(q_vdb_pkg_ctx *pkg_ctx)
+static int
+cmpstringp(const void *p1, const void *p2)
+{
+	/* case insensitive comparator */
+	return strcasecmp(*((char * const *)p1), *((char * const *)p2));
+}
+
+/*
+ * ==> /var/db/pkg/mail-mta/exim-4.92/IUSE <==
+ * arc dane dcc +dkim dlfunc dmarc +dnsdb doc dovecot-sasl dsn
+ * elibc_glibc exiscan-acl gnutls idn ipv6 ldap libressl lmtp maildir
+ * mbx mysql nis pam perl pkcs11 postgres +prdr proxy radius redis sasl
+ * selinux spf sqlite srs ssl syslog tcpd +tpda X
+ *
+ * ==> /var/db/pkg/mail-mta/exim-4.92/PKGUSE <==
+ * -X dkim dmarc exiscan-acl ipv6 -ldap lmtp maildir -mbox pam -perl spf
+ * ssl tcpd
+ *
+ * ==> /var/db/pkg/mail-mta/exim-4.92/USE <==
+ * abi_x86_64 amd64 dkim dmarc dnsdb elibc_glibc exiscan-acl ipv6
+ * kernel_linux lmtp maildir pam prdr spf ssl tcpd tpda userland_GNU
+ *
+ * % emerge -pv exim
+ *
+ * These are the packages that would be merged, in order:
+ *
+ * Calculating dependencies... done!
+ * [ebuild   R   ~] mail-mta/exim-4.92::gentoo  USE="dkim dmarc dnsdb
+ * exiscan-acl ipv6 lmtp maildir pam prdr spf ssl tcpd tpda -X -arc
+ * -dane -dcc -dlfunc -doc -dovecot-sasl -dsn -gnutls -idn -ldap
+ * -libressl -mbx -mysql -nis -perl -pkcs11 -postgres -proxy -radius
+ * -redis -sasl (-selinux) -sqlite -srs -syslog" 0 KiB
+ *
+ * % qlist -IUv exim
+ * mail-mta/exim-4.92 (-arc -dane -dcc dkim -dlfunc dmarc dnsdb -doc
+ * -dovecot-sasl -dsn exiscan-acl -gnutls -idn ipv6 -ldap -libressl lmtp
+ * maildir -mbx -mysql -nis pam -perl -pkcs11 -postgres prdr -proxy
+ * -radius -redis -sasl -selinux spf -sqlite -srs ssl -syslog tcpd tpda
+ * -X)
+ */
+static char _umapstr_buf[BUFSIZ];
+static const char *
+umapstr(char display, q_vdb_pkg_ctx *pkg_ctx)
 {
-	static char umap[BUFSIZ];
-	static char *use, *iuse;
-	static size_t use_len, iuse_len;
-	int use_argc = 0, iuse_argc = 0;
-	char **use_argv = NULL, **iuse_argv = NULL;
-	queue *ll = NULL;
-	queue *sets = NULL;
-	int i, u;
+	char *bufp = _umapstr_buf;
+	char *use = NULL;
+	char *iuse = NULL;
+	size_t use_len;
+	size_t iuse_len;
+	int use_argc = 0;
+	int iuse_argc = 0;
+	char **use_argv = NULL;
+	char **iuse_argv = NULL;
+	int i;
+	int u;
+	int d;
+
+	*bufp = '\0';
+	if (!display)
+		return bufp;
 
 	q_vdb_pkg_eat(pkg_ctx, "USE", &use, &use_len);
 	if (!use[0])
-		return NULL;
+		return bufp;
 	q_vdb_pkg_eat(pkg_ctx, "IUSE", &iuse, &iuse_len);
 	if (!iuse[0])
-		return NULL;
-
-	umap[0] = '\0'; /* reset the buffer */
+		return bufp;
 
-	makeargv(use, &use_argc, &use_argv);
 	/* strip out possible leading +/- flags in IUSE */
-	for (i = 0; i < (int)strlen(iuse); i++)
+	u = (int)strlen(iuse);
+	for (i = 0; i < u; i++)
 		if (iuse[i] == '+' || iuse[i] == '-')
 			if (i == 0 || iuse[i - 1] == ' ')
 				iuse[i] = ' ';
+
+	makeargv(use, &use_argc, &use_argv);
 	makeargv(iuse, &iuse_argc, &iuse_argv);
-	for (u = 1; u < use_argc; u++) {
-		for (i = 1; i < iuse_argc; i++) {
-			if (strcmp(use_argv[u], iuse_argv[i]) == 0) {
-				strncat(umap, use_argv[u], sizeof(umap)-strlen(umap)-1);
-				strncat(umap, " ", sizeof(umap)-strlen(umap)-1);
-			}
+
+#define add_to_buf(fmt, Cb, use, Ce) \
+	bufp += snprintf(bufp, sizeof(_umapstr_buf) - (bufp - _umapstr_buf), \
+			" %s%s" fmt "%s", \
+			bufp == _umapstr_buf && !quiet ? "(" : "", Cb, use, Ce);
+
+	/* merge join, ensure inputs are sorted (Portage does this, but just
+	 * to be sure) */
+	qsort(&use_argv[1], use_argc - 1, sizeof(char *), cmpstringp);
+	qsort(&iuse_argv[1], iuse_argc - 1, sizeof(char *), cmpstringp);
+	for (i = 1, u = 1; i < iuse_argc; i++) {
+		/* filter out implicits */
+		if (strncmp(iuse_argv[i], "elibc_", 6) == 0 ||
+				strncmp(iuse_argv[i], "kernel_", 7) == 0 ||
+				strncmp(iuse_argv[i], "userland_", 9) == 0)
+			continue;
+
+		/* ensure USE is in IUSE */
+		for (d = 1; u < use_argc; u++) {
+			d = strcmp(use_argv[u], iuse_argv[i]);
+			if (d >= 0)
+				break;
 		}
-	}
-	freeargv(iuse_argc, iuse_argv);
-	freeargv(use_argc, use_argv);
 
-	/* filter out the dup use flags */
-	use_argc = 0; use_argv = NULL;
-	makeargv(umap, &use_argc, &use_argv);
-	for (i = 1; i < use_argc; i++) {
-		int ok = 0;
-		sets = del_set(use_argv[i], sets, &ok);
-		sets = add_set(use_argv[i], sets);
-	}
-	umap[0] = '\0'; /* reset the buffer */
-	for (ll = sets; ll != NULL; ll = ll->next) {
-		strncat(umap, ll->name, sizeof(umap)-strlen(umap)-1);
-		strncat(umap, " ", sizeof(umap)-strlen(umap)-1);
+		if (d == 0) {
+			add_to_buf("%s", RED, iuse_argv[i], NORM);
+			u++;
+		} else if (verbose) {
+			add_to_buf("-%s", DKBLUE, iuse_argv[i], NORM);
+		}
 	}
-	freeargv(use_argc, use_argv);
-	free_sets(sets);
-	/* end filter */
 
-	return umap;
-}
+	bufp += snprintf(bufp, sizeof(_umapstr_buf) - (bufp - _umapstr_buf),
+			"%s", bufp == _umapstr_buf || quiet ? "" : ")");
 
-static const char *
-umapstr(char display, q_vdb_pkg_ctx *pkg_ctx)
-{
-	static char buf[BUFSIZ];
-	char *umap = NULL;
+	freeargv(iuse_argc, iuse_argv);
+	freeargv(use_argc, use_argv);
+	free(iuse);
+	free(use);
 
-	buf[0] = '\0';
-	if (!display)
-		return buf;
-	if ((umap = grab_pkg_umap(pkg_ctx)) == NULL)
-		return buf;
-	rmspace(umap);
-	if (!strlen(umap))
-		return buf;
-	snprintf(buf, sizeof(buf), " %s%s%.*s%s%s",
-			quiet ? "": "(", RED,
-			(int)(sizeof(buf) - (quiet ? 3 : 1) - sizeof(RED) - sizeof(NORM)),
-			umap, NORM, quiet ? "": ")");
-	return buf;
+	return _umapstr_buf;
 }
 
 static bool
@@ -308,14 +348,23 @@ qlist_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 				}
 			}
 			if (state->show_repo && !pkg_ctx->repo)
-				q_vdb_pkg_eat(pkg_ctx, "repository", &pkg_ctx->repo, &pkg_ctx->repo_len);
+				q_vdb_pkg_eat(pkg_ctx, "repository",
+						&pkg_ctx->repo, &pkg_ctx->repo_len);
 			/* display it */
-			printf("%s%s/%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", BOLD, catname, BLUE,
-				(!state->columns ? (atom ? atom->PN : pkgname) : atom->PN),
-				(state->columns ? " " : ""), (state->columns ? atom->PV : ""),
-				NORM, YELLOW, state->show_slots ? ":" : "", state->show_slots ? pkg_ctx->slot : "", NORM,
-				NORM, GREEN, state->show_repo ? "::" : "", state->show_repo ? pkg_ctx->repo : "", NORM,
-				umapstr(state->show_umap, pkg_ctx));
+			printf("%s%s/%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+					BOLD, catname, BLUE,
+					(!state->columns ? (atom ? atom->PN : pkgname) : atom->PN),
+					(state->columns ? " " : ""),
+					(state->columns ? atom->PV : ""),
+					NORM, YELLOW,
+					state->show_slots ? ":" : "",
+					state->show_slots ? pkg_ctx->slot : "",
+					NORM,
+					NORM, GREEN,
+					state->show_repo ? "::" : "",
+					state->show_repo ? pkg_ctx->repo : "",
+					NORM,
+					umapstr(state->show_umap, pkg_ctx));
 		}
 		if (atom)
 			atom_implode(atom);


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-03-29 16:35 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-03-29 16:35 UTC (permalink / raw
  To: gentoo-commits

commit:     c701892114d5b3eea773ff13f013f4d3a71fa571
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri Mar 29 16:31:50 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri Mar 29 16:31:50 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c7018921

qlop: support standard date output format in parse_date

This allows to cut 'n' paste dates to limit output.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qlop.optdesc.yaml |  3 +++
 man/qlop.1                    |  5 ++++-
 qlop.c                        | 14 +++++++++-----
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/man/include/qlop.optdesc.yaml b/man/include/qlop.optdesc.yaml
index a8fae61..25143b2 100644
--- a/man/include/qlop.optdesc.yaml
+++ b/man/include/qlop.optdesc.yaml
@@ -13,6 +13,9 @@ date: |
     .IP YYYY-MM-DD
     Big-endian date, with components separated by hyphens, starting with
     year, followed by month and day of month.
+    .IP YYYY-MM-DDThh:mm:ss
+    As before, but hours, minutes and seconds added.  This is the same
+    format qlop prints for timestamps.
     .IP SSSSSSSSS
     Seconds since 1970-01-01 00:00:00 +0000 (UTC), the UNIX epoch.
     .IP FORMAT|DATE

diff --git a/man/qlop.1 b/man/qlop.1
index 407c9ea..f0ef69a 100644
--- a/man/qlop.1
+++ b/man/qlop.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH qlop "1" "Feb 2019" "Gentoo Foundation" "qlop"
+.TH qlop "1" "Mar 2019" "Gentoo Foundation" "qlop"
 .SH NAME
 qlop \- emerge log analyzer
 .SH SYNOPSIS
@@ -89,6 +89,9 @@ Alias for \fI1 day ago\fR.
 .IP YYYY-MM-DD
 Big-endian date, with components separated by hyphens, starting with
 year, followed by month and day of month.
+.IP YYYY-MM-DDThh:mm:ss
+As before, but hours, minutes and seconds added.  This is the same
+format qlop prints for timestamps.
 .IP SSSSSSSSS
 Seconds since 1970-01-01 00:00:00 +0000 (UTC), the UNIX epoch.
 .IP FORMAT|DATE

diff --git a/qlop.c b/qlop.c
index b6970d0..a87cc5c 100644
--- a/qlop.c
+++ b/qlop.c
@@ -103,17 +103,21 @@ parse_date(const char *sdate, time_t *t)
 			return false;
 	} else {
 		/* Handle automatic formats:
-		 * - "12315128"   -> %s
-		 * - "2015-12-24" -> %Y-%m-%d
+		 * - "12315128"            -> %s
+		 * - "2015-12-24"          -> %Y-%m-%d
+		 * - "2019-03-28T13:52:31" -> %Y-%m-%dT%H:%M:%s"
 		 * - human readable format (see below)
 		 */
-		size_t len = strspn(sdate, "0123456789-");
+		size_t len = strspn(sdate, "0123456789-:T");
 		if (sdate[len] == '\0') {
 			const char *fmt;
-			if (strchr(sdate, '-') == NULL)
+			if (strchr(sdate, '-') == NULL) {
 				fmt = "%s";
-			else
+			} else if ((s = strchr(sdate, 'T')) == NULL) {
 				fmt = "%Y-%m-%d";
+			} else {
+				fmt = "%Y-%m-%dT%H:%M:%S";
+			}
 
 			s = strptime(sdate, fmt, &tm);
 			if (s == NULL || s[0] != '\0')


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-04-28  7:58 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-04-28  7:58 UTC (permalink / raw
  To: gentoo-commits

commit:     c5aba3a0bd055688120dbabb9c3826ed46ffc795
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 28 07:57:05 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Apr 28 07:57:05 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c5aba3a0

qgrep: rewrite using libq/vdb and libq/cache

(re)use the traversion logic from libq instead of re-implementing this.
Additional benefits are less code and usage of metadata when available.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 applets.h                      |   2 +-
 man/include/qgrep.desc         |   9 +-
 man/include/qgrep.optdesc.yaml |   5 +-
 man/q.1                        |   2 +-
 man/qgrep.1                    |  16 +-
 qgrep.c                        | 756 ++++++++++++++++++++++-------------------
 6 files changed, 429 insertions(+), 361 deletions(-)

diff --git a/applets.h b/applets.h
index 5889de6..4dd5bc2 100644
--- a/applets.h
+++ b/applets.h
@@ -73,7 +73,7 @@ static const struct applet_t {
 	/*
 	{"qglsa",     qglsa_main,     "<action> <list>", "check GLSAs against system"},
 	*/
-	{"qgrep",     qgrep_main,     "<misc args>",     "grep in ebuilds"},
+	{"qgrep",     qgrep_main,     "<expr> [pkg ...]", "grep in ebuilds"},
 	{"qlist",     qlist_main,     "<pkgname>",       "list files owned by pkgname"},
 	{"qlop",      qlop_main,      "<pkgname>",       "emerge log analyzer"},
 	{"qmerge",    qmerge_main,    "<pkgnames>",      "fetch and merge binary package"},

diff --git a/man/include/qgrep.desc b/man/include/qgrep.desc
index c95d35a..98bcc09 100644
--- a/man/include/qgrep.desc
+++ b/man/include/qgrep.desc
@@ -1,3 +1,6 @@
-\fIqgrep\fR searches for a given pattern in all ebuilds of the current
-portage tree.  Optionally the search is in all eclasses, or just in the
-ebuilds that are currently installed.
+\fIqgrep\fR searches for a given expression in all ebuilds of the
+current portage tree and defined additional overlays.  Optionally the
+search is in all eclasses, or just in the ebuilds that are currently
+installed.  To narrow the search, multiple targets can be given using
+atom syntax.  In particular, the trailing slash (/) syntax can be used
+to match an entire category.  See also \fIqatom\fR(1).

diff --git a/man/include/qgrep.optdesc.yaml b/man/include/qgrep.optdesc.yaml
index 87b174e..ad3874d 100644
--- a/man/include/qgrep.optdesc.yaml
+++ b/man/include/qgrep.optdesc.yaml
@@ -1,5 +1,4 @@
 verbose: |
-    Print multiple matches per files.  When this option is given
-    multiple times, also linenumber are printed for matches next to file
-    names.
+    Prefix each matching line with filename (like \fB-H\fR).  When this
+    option is given multiple times, also linenumbers are printed.
 quiet: Ignored for compatibility with other qapplets.

diff --git a/man/q.1 b/man/q.1
index b3e985b..afba24a 100644
--- a/man/q.1
+++ b/man/q.1
@@ -41,7 +41,7 @@ Print version and exit.
    qcheck <pkgname>       : verify integrity of installed packages
  qdepends <pkgname>       : show dependency info
     qfile <filename>      : list all pkgs owning files
-    qgrep <misc args>     : grep in ebuilds
+    qgrep <expr> [pkg ...]: grep in ebuilds
     qlist <pkgname>       : list files owned by pkgname
      qlop <pkgname>       : emerge log analyzer
    qmerge <pkgnames>      : fetch and merge binary package

diff --git a/man/qgrep.1 b/man/qgrep.1
index 662122d..048e28e 100644
--- a/man/qgrep.1
+++ b/man/qgrep.1
@@ -4,11 +4,14 @@
 qgrep \- grep in ebuilds
 .SH SYNOPSIS
 .B qgrep
-\fI[opts] <misc args>\fR
+\fI[opts] <expr> [pkg ...]\fR
 .SH DESCRIPTION
-\fIqgrep\fR searches for a given pattern in all ebuilds of the current
-portage tree.  Optionally the search is in all eclasses, or just in the
-ebuilds that are currently installed.
+\fIqgrep\fR searches for a given expression in all ebuilds of the
+current portage tree and defined additional overlays.  Optionally the
+search is in all eclasses, or just in the ebuilds that are currently
+installed.  To narrow the search, multiple targets can be given using
+atom syntax.  In particular, the trailing slash (/) syntax can be used
+to match an entire category.  See also \fIqatom\fR(1).
 .SH OPTIONS
 .TP
 \fB\-I\fR, \fB\-\-invert\-match\fR
@@ -60,9 +63,8 @@ Print <arg> lines of trailing context.
 Set the ROOT env var.
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
-Print multiple matches per files.  When this option is given
-multiple times, also linenumber are printed for matches next to file
-names.
+Prefix each matching line with filename (like \fB-H\fR).  When this
+option is given multiple times, also linenumbers are printed.
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
 Ignored for compatibility with other qapplets.

diff --git a/qgrep.c b/qgrep.c
index 16bb4c1..3950c22 100644
--- a/qgrep.c
+++ b/qgrep.c
@@ -64,35 +64,6 @@ static const char * const qgrep_opts_help[] = {
 };
 #define qgrep_usage(ret) usage(ret, QGREP_FLAGS, qgrep_long_opts, qgrep_opts_help, NULL, lookup_applet_idx("qgrep"))
 
-static char
-qgrep_name_match(const char* name, const int argc, depend_atom** argv)
-{
-	depend_atom* atom;
-	int i;
-
-	if ((atom = atom_explode(name)) == NULL)
-		return 0;
-
-	for (i = 0; i < argc; i++) {
-		if (argv[i] == NULL)
-			continue;
-		if (atom->CATEGORY && argv[i]->CATEGORY && *(argv[i]->CATEGORY)
-				&& strcmp(atom->CATEGORY, argv[i]->CATEGORY))
-			continue;
-		if (atom->PN && argv[i]->PN && *(argv[i]->PN)
-				&& strcmp(atom->PN, argv[i]->PN))
-			continue;
-		if (atom->PVR && argv[i]->PVR && *(argv[i]->PVR)
-				&& strcmp(atom->PVR, argv[i]->PVR))
-			continue;
-		atom_implode(atom);
-		return 1;
-	}
-
-	atom_implode(atom);
-	return 0;
-}
-
 /* Circular list of line buffers for --before */
 typedef struct qgrep_buf {
 	char valid;
@@ -221,91 +192,356 @@ qgrep_print_before_context(qgrep_buf_t *current, const char num_lines_before,
 	}
 }
 
-/* Yield the path of one of the installed ebuilds (from VDB). */
-static char *
-get_next_installed_ebuild(
-		char *ebuild_path,
-		size_t ebuild_path_len,
-		DIR *vdb_dir,
-		struct dirent **cat_dirent_pt,
-		DIR **cat_dir_pt)
+struct qgrep_grepargs {
+	bool do_count:1;
+	bool do_regex:1;
+	bool do_list:1;
+	bool show_filename:1;
+	bool show_name:1;
+	bool skip_comments:1;
+	bool invert_list:1;
+	bool invert_match:1;
+	char *skip_pattern;
+	char num_lines_before;
+	char num_lines_after;
+	qgrep_buf_t *buf_list;
+	regex_t skip_preg;
+	regex_t preg;
+	const char *query;
+	QGREP_STR_FUNC strfunc;
+	depend_atom **include_atoms;
+	const char *portdir;
+};
+
+static int
+qgrep_grepat(int fd, const char *file, const char *label,
+		struct qgrep_grepargs *a)
+{
+	FILE *newfp;
+	int need_separator = 0;
+	int count = 0;
+	int lineno = 0;
+	char remaining_after_context = 0;
+	char status = 1;
+	char *p;
+	bool per_file_output;
+
+	/* do we report results once per file or per line ? */
+	per_file_output =
+		a->do_count || (a->do_list && (!verbose || a->invert_list));
+
+	if (fd >= 0) {
+		int sfd = openat(fd, file, O_RDONLY|O_CLOEXEC);
+		newfp = sfd >= 0 ? fdopen(sfd, "r") : NULL;
+	} else {
+		newfp = fopen(file, "r");
+	}
+	if (newfp == NULL)
+		return status;
+
+	count = 0;
+	/* if there have been some matches already, then a
+	 * separator will be needed */
+	need_separator =
+		!status && (a->num_lines_before || a->num_lines_after);
+	/* whatever is in the circular buffers list is no more a
+	 * valid context */
+	qgrep_buf_list_invalidate(a->buf_list);
+
+	/* reading a new line always happen in the next buffer
+	 * of the list */
+	while ((a->buf_list = a->buf_list->next) &&
+			fgets(a->buf_list->buf, sizeof(a->buf_list->buf), newfp))
+	{
+		lineno++;
+		a->buf_list->valid = 1;
+
+		/* cleanup EOL */
+		if ((p = strrchr(a->buf_list->buf, '\n')) != NULL)
+			*p = 0;
+		if ((p = strrchr(a->buf_list->buf, '\r')) != NULL)
+			*p = 0;
+
+		if (a->skip_comments) {
+			/* reject comments line ("^[ \t]*#") */
+			p = a->buf_list->buf;
+			while (*p == ' ' || *p == '\t') p++;
+			if (*p == '#')
+				goto print_after_context;
+		}
+
+		if (a->skip_pattern) {
+			/* reject some other lines which match an
+			 * optional pattern */
+			if (!a->do_regex) {
+				if (a->strfunc(a->buf_list->buf, a->skip_pattern) != NULL)
+					goto print_after_context;
+			} else {
+				if (regexec(&a->skip_preg, a->buf_list->buf,
+							0, NULL, 0) == 0)
+					goto print_after_context;
+			}
+		}
+
+		/* four ways to match a line (with/without inversion
+		 * and regexp) */
+		if (!a->invert_match) {
+			if (a->do_regex == 0) {
+				if (a->strfunc(a->buf_list->buf, a->query) == NULL)
+					goto print_after_context;
+			} else {
+				if (regexec(&a->preg, a->buf_list->buf, 0, NULL, 0) != 0)
+					goto print_after_context;
+			}
+		} else {
+			if (a->do_regex == 0) {
+				if (a->strfunc(a->buf_list->buf, a->query) != NULL)
+					goto print_after_context;
+			} else {
+				if (regexec(&a->preg, a->buf_list->buf, 0, NULL, 0) == 0)
+					goto print_after_context;
+			}
+		}
+
+		count++;
+		status = 0; /* got a match, exit status should be 0 */
+		if (per_file_output)
+			continue;
+		/* matching files are listed out of this loop */
+
+		if ((need_separator > 0)
+				&& (a->num_lines_before || a->num_lines_after))
+			printf("--\n");
+		/* "need_separator" is not a flag, but a counter, so that
+		 * adjacent contextes are not separated */
+		need_separator = 0 - a->num_lines_before;
+		if (!a->do_list) {
+			/* print the leading context */
+			qgrep_print_before_context(a->buf_list,
+					a->num_lines_before, label,
+					((verbose > 1) ? lineno : -1));
+			/* print matching line */
+			if (a->invert_match || *RED == '\0')
+				qgrep_print_matching_line_nocolor(a->buf_list, label,
+						((verbose > 1) ? lineno : -1));
+			else if (a->do_regex)
+				qgrep_print_matching_line_regcolor(a->buf_list, label,
+						((verbose > 1) ? lineno : -1), &a->preg);
+			else
+				qgrep_print_matching_line_strcolor(a->buf_list, label,
+						((verbose > 1) ? lineno : -1), a->strfunc,
+						a->query);
+		} else {
+			/* in verbose do_list mode, list the file once
+			 * per match */
+			printf("%s", label);
+			if (verbose > 1)
+				printf(":%d", lineno);
+			putchar('\n');
+		}
+		/* init count down of trailing context lines */
+		remaining_after_context = a->num_lines_after;
+		continue;
+
+print_after_context:
+		/* print some trailing context lines when needed */
+		if (!remaining_after_context) {
+			if (!status)
+				/* we're getting closer to the need of a
+				 * separator between current match block and
+				 * the next one */
+				++need_separator;
+		} else {
+			qgrep_print_context_line(a->buf_list, label,
+					((verbose > 1) ? lineno : -1));
+			--remaining_after_context;
+		}
+	}
+	fclose(newfp);
+	if (per_file_output) {
+		/* matches were already displayed, line per line */
+		if (a->do_count && count) {
+			if (label != NULL)
+				/* -c without -v/-N/-H only outputs
+				 * the matches count of the file */
+				printf("%s:", label);
+			printf("%d\n", count);
+		} else if ((count && !a->invert_list) ||
+				(!count && a->invert_list))
+		{
+			printf("%s\n", label);
+		}
+		/* do_list == 1, or we wouldn't be here */
+	}
+
+	return status;
+}
+
+static int
+qgrep_cache_cb(cache_pkg_ctx *pkg_ctx, void *priv)
+{
+	struct qgrep_grepargs *data = (struct qgrep_grepargs *)priv;
+	char buf[_Q_PATH_MAX];
+	char name[_Q_PATH_MAX];
+	char *label;
+	depend_atom *patom = NULL;
+	cache_ctx *cctx;
+	int ret;
+	int pfd;
+
+	snprintf(buf, sizeof(buf), "%s/%s",
+			pkg_ctx->cat_ctx->name, pkg_ctx->name);
+	patom = atom_explode(buf);
+	if (patom == NULL)
+		return EXIT_FAILURE;
+
+	if (data->include_atoms != NULL) {
+		depend_atom **d;
+		for (d = data->include_atoms; *d != NULL; d++) {
+			if (atom_compare(patom, *d) == EQUAL)
+				break;
+		}
+		if (*d == NULL) {
+			atom_implode(patom);
+			return EXIT_FAILURE;
+		}
+	}
+
+	/* need to construct path in portdir to ebuild, pass it to grep */
+	cctx = (cache_ctx *)(pkg_ctx->cat_ctx->ctx);
+	if (cctx->cachetype == CACHE_EBUILD) {
+		pfd = cctx->dir_ctx->vdb_fd;
+	} else {
+		pfd = openat(cctx->dir_ctx->vdb_fd, "../..", O_RDONLY|O_CLOEXEC);
+	}
+
+	/* cat/pkg/pkg-ver.ebuild */
+	snprintf(buf, sizeof(buf), "%s/%s/%s.ebuild",
+			patom->CATEGORY, patom->PN, patom->P);
+
+	label = NULL;
+	if (data->show_name) {
+		snprintf(name, sizeof(name), "%s/%s", patom->CATEGORY, patom->P);
+		label = name;
+	} else if (data->show_filename) {
+		label = buf;
+	}
+
+	ret = qgrep_grepat(pfd, buf, label, data);
+
+	atom_implode(patom);
+
+	return ret;
+}
+
+static int
+qgrep_vdb_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 {
-	struct dirent *pkg_dirent = NULL;
-	if (*cat_dirent_pt == NULL || *cat_dir_pt == NULL)
-		goto get_next_category;
-get_next_ebuild_from_category:
-	if ((pkg_dirent = readdir(*cat_dir_pt)) == NULL)
-		goto get_next_category;
-	if (pkg_dirent->d_name[0] == '.')
-		goto get_next_ebuild_from_category;
-	snprintf(ebuild_path, ebuild_path_len, "%s/%s/%s.ebuild",
-			(*cat_dirent_pt)->d_name, pkg_dirent->d_name, pkg_dirent->d_name);
-	return ebuild_path;
-get_next_category:
-	if (*cat_dir_pt != NULL)
-		closedir(*cat_dir_pt);
-	*cat_dirent_pt = q_vdb_get_next_dir(vdb_dir);
-	if (*cat_dirent_pt == NULL)
-		return NULL;
-	if ((*cat_dir_pt = opendir((*cat_dirent_pt)->d_name)) == NULL)
-		goto get_next_category;
-	goto get_next_ebuild_from_category;
+	struct qgrep_grepargs *data = (struct qgrep_grepargs *)priv;
+	char buf[_Q_PATH_MAX];
+	char name[_Q_PATH_MAX];
+	char *label;
+	depend_atom *patom = NULL;
+	int ret;
+	int pfd;
+
+	snprintf(buf, sizeof(buf), "%s/%s",
+			pkg_ctx->cat_ctx->name, pkg_ctx->name);
+	patom = atom_explode(buf);
+	if (patom == NULL)
+		return EXIT_FAILURE;
+
+	if (data->include_atoms != NULL) {
+		depend_atom **d;
+		for (d = data->include_atoms; *d != NULL; d++) {
+			if (atom_compare(patom, *d) == EQUAL)
+				break;
+		}
+		if (*d == NULL) {
+			atom_implode(patom);
+			return EXIT_FAILURE;
+		}
+	}
+
+	/* get path to portdir */
+	pfd = openat(pkg_ctx->cat_ctx->ctx->portroot_fd,
+			data->portdir, O_RDONLY|O_CLOEXEC);
+
+	/* cat/pkg/pkg-ver.ebuild */
+	snprintf(buf, sizeof(buf), "%s/%s/%s.ebuild",
+			patom->CATEGORY, patom->PN, patom->P);
+
+	label = NULL;
+	if (data->show_name) {
+		snprintf(name, sizeof(name), "%s/%s", patom->CATEGORY, patom->P);
+		label = name;
+	} else if (data->show_filename) {
+		label = buf;
+	}
+
+	ret = qgrep_grepat(pfd, buf, label, data);
+
+	atom_implode(patom);
+
+	return ret;
 }
 
 int qgrep_main(int argc, char **argv)
 {
 	int i;
-	int count = 0;
 	char *p;
-	char do_count, do_regex, do_eclass, do_installed, do_list;
-	char show_filename, skip_comments, invert_list, show_name;
-	char per_file_output;
-	FILE *fp = NULL;
+	bool do_eclass;
+	bool do_installed;
 	DIR *eclass_dir = NULL;
-	DIR *vdb_dir = NULL;
-	DIR *cat_dir = NULL;
 	struct dirent *dentry = NULL;
-	char ebuild[_Q_PATH_MAX * 4];
-	char name[_Q_PATH_MAX * 2];
-	char *label;
 	int reflags = 0;
-	char invert_match = 0;
-	regex_t preg, skip_preg;
-	char *skip_pattern = NULL;
-	depend_atom** include_atoms = NULL;
 	unsigned long int context_optarg;
-	char num_lines_before = 0;
-	char num_lines_after = 0;
-	qgrep_buf_t *buf_list;
-	int need_separator = 0;
 	char status = 1;
+	size_t n;
+	char *overlay;
 
-	QGREP_STR_FUNC strfunc = strstr;
-
-	do_count = do_regex = do_eclass = do_installed = do_list = 0;
-	show_filename = skip_comments = invert_list = show_name = 0;
+	struct qgrep_grepargs args = {
+		.do_count = 0,
+		.do_regex = 0,
+		.do_list = 0,
+		.show_filename = 0,
+		.show_name = 0,
+		.skip_comments = 0,
+		.invert_list = 0,
+		.invert_match = 0,
+		.skip_pattern = NULL,
+		.num_lines_before = 0,
+		.num_lines_after = 0,
+		.buf_list = NULL,
+		.query = NULL,
+		.strfunc = strstr,
+		.include_atoms = NULL,
+		.portdir = NULL,
+	};
+
+	do_eclass = do_installed = 0;
 
 	while ((i = GETOPT_LONG(QGREP, qgrep, "")) != -1) {
 		switch (i) {
-		case 'I': invert_match = 1; break;
+		case 'I': args.invert_match = 1; break;
 		case 'i':
-			strfunc = strcasestr;
+			args.strfunc = strcasestr;
 			reflags |= REG_ICASE;
 			break;
-		case 'c': do_count = 1; break;
-		case 'l': do_list = 1; break;
-		case 'L': do_list = invert_list = 1; break;
-		case 'e': do_regex = 1; break;
+		case 'c': args.do_count = 1; break;
+		case 'l': args.do_list = 1; break;
+		case 'L': args.do_list = args.invert_list = 1; break;
+		case 'e': args.do_regex = 1; break;
 		case 'x':
-			do_regex = 1;
+			args.do_regex = 1;
 			reflags |= REG_EXTENDED;
 			break;
 		case 'J': do_installed = 1; break;
 		case 'E': do_eclass = 1; break;
-		case 'H': show_filename = 1; break;
-		case 'N': show_name = 1; break;
-		case 's': skip_comments = 1; break;
-		case 'S': skip_pattern = optarg; break;
+		case 'H': args.show_filename = 1; break;
+		case 'N': args.show_name = 1; break;
+		case 's': args.skip_comments = 1; break;
+		case 'S': args.skip_pattern = optarg; break;
 		case 'B':
 		case 'A':
 			errno = 0;
@@ -317,9 +553,9 @@ int qgrep_main(int argc, char **argv)
 			if (context_optarg > 254)
 				err("%s: silly value!", optarg);
 			if (i == 'B')
-				num_lines_before = context_optarg;
+				args.num_lines_before = context_optarg;
 			else
-				num_lines_after = context_optarg;
+				args.num_lines_after = context_optarg;
 			break;
 		COMMON_GETOPTS_CASES(qgrep)
 		}
@@ -327,312 +563,140 @@ int qgrep_main(int argc, char **argv)
 	if (argc == optind)
 		qgrep_usage(EXIT_FAILURE);
 
-	if (do_list && do_count) {
+	if (args.do_list && args.do_count) {
 		warn("%s and --count are incompatible options. The former wins.",
-				(invert_list ? "--invert-list" : "--list"));
-		do_count = 0;
+				(args.invert_list ? "--invert-list" : "--list"));
+		args.do_count = false;
 	}
 
-	if (show_name && show_filename) {
+	if (args.show_name && args.show_filename) {
 		warn("--with-name and --with-filename are incompatible options. "
 				"The former wins.");
-		show_filename = 0;
+		args.show_filename = false;
 	}
 
-	if (do_list && num_lines_before) {
+	if (args.do_list && args.num_lines_before) {
 		warn("%s and --before are incompatible options. The former wins.",
-				(invert_list ? "--invert-list" : "--list"));
-		num_lines_before = 0;
+				(args.invert_list ? "--invert-list" : "--list"));
+		args.num_lines_before = 0;
 	}
 
-	if (do_list && num_lines_after) {
+	if (args.do_list && args.num_lines_after) {
 		warn("%s and --after are incompatible options. The former wins.",
-				(invert_list ? "--invert-list" : "--list"));
-		num_lines_after = 0;
+				(args.invert_list ? "--invert-list" : "--list"));
+		args.num_lines_after = 0;
 	}
 
-	if (do_count && num_lines_before) {
+	if (args.do_count && args.num_lines_before) {
 		warn("--count and --before are incompatible options. The former wins.");
-		num_lines_before = 0;
+		args.num_lines_before = 0;
 	}
 
-	if (do_count && num_lines_after) {
+	if (args.do_count && args.num_lines_after) {
 		warn("--count and --after are incompatible options. The former wins.");
-		num_lines_after = 0;
+		args.num_lines_after = 0;
 	}
 
 	if (do_installed && do_eclass) {
 		warn("--installed and --eclass are incompatible options. "
 				"The former wins.");
-		do_eclass = 0;
+		do_eclass = false;
 	}
 
-	/* do we report results once per file or per line ? */
-	per_file_output = do_count || (do_list && (!verbose || invert_list));
-	/* label for prefixing matching lines or listing matching files */
-	label = (show_name ? name :
-			((verbose || show_filename || do_list) ? ebuild : NULL));
-
 	if (argc > (optind + 1)) {
-		include_atoms = xcalloc(sizeof(depend_atom*), (argc - optind - 1));
-		for (i = (optind + 1); i < argc; i++)
-			if ((include_atoms[i - optind - 1] = atom_explode(argv[i])) == NULL)
+		depend_atom **d = args.include_atoms =
+			xcalloc(sizeof(depend_atom *), (argc - optind - 1) + 1);
+		for (i = (optind + 1); i < argc; i++) {
+			*d = atom_explode(argv[i]);
+			if (*d == NULL) {
 				warn("%s: invalid atom, will be ignored", argv[i]);
+			} else {
+				d++;
+			}
+		}
+		*d = NULL;
 	}
 
+	/* make it easier to see what needs to be printed */
+	if (!args.show_name && (verbose || args.do_list))
+		args.show_filename = true;
+
 	/* pre-compile regexps once for all */
-	if (do_regex) {
-		if (invert_match || *RED == '\0')
+	if (args.do_regex) {
+		if (args.invert_match || *RED == '\0')
 			reflags |= REG_NOSUB;
-		xregcomp(&preg, argv[optind], reflags);
+		xregcomp(&args.preg, argv[optind], reflags);
 		reflags |= REG_NOSUB;
-		if (skip_pattern)
-			xregcomp(&skip_preg, skip_pattern, reflags);
+		if (args.skip_pattern)
+			xregcomp(&args.skip_preg, args.skip_pattern, reflags);
 	}
+	args.query = argv[optind];
 
 	/* allocate a circular buffers list for --before */
-	buf_list = qgrep_buf_list_alloc(num_lines_before + 1);
+	args.buf_list = qgrep_buf_list_alloc(args.num_lines_before + 1);
 
-	size_t n;
-	char *overlay;
 	array_for_each(overlays, n, overlay) {
+		args.portdir = overlay;
+		if (do_eclass) {
+			char buf[_Q_PATH_MAX];
+			char name[_Q_PATH_MAX];
+			char *label;
+			int efd;
 
-		/* go look either in ebuilds or eclasses or VDB */
-		/* FIXME: use libq/vdb and libq/cache here */
-		if (!do_eclass && !do_installed) {
-			/* TODO: use libq/cache here */ continue;
-		} else if (do_eclass) {
-			xchdir(overlay);
-			if ((eclass_dir = opendir("eclass")) == NULL) {
+			snprintf(buf, sizeof(buf), "%s/%s/eclass", portroot, overlay);
+			efd = open(buf, O_RDONLY|O_CLOEXEC);
+			if (efd == -1 || (eclass_dir = fdopendir(efd)) == NULL) {
 				if (errno != ENOENT)
 					warnp("opendir(\"%s/eclass\") failed", overlay);
 				continue;
 			}
-		} else { /* if (do_install) */
-			/* TODO: use libq/vdb here */
-			char buf[_Q_PATH_MAX];
-			snprintf(buf, sizeof(buf), "%s/%s", portroot, portvdb);
-			xchdir(buf);
-			if ((vdb_dir = opendir(".")) == NULL)
-				errp("could not opendir(%s/%s) for ROOT/VDB",
-						portroot, portvdb);
-		}
-
-		/* iteration is either over ebuilds or eclasses */
-		while (do_eclass
-				? ((dentry = readdir(eclass_dir))
-					&& snprintf(ebuild, sizeof(ebuild),
-						"eclass/%s", dentry->d_name))
-				: (do_installed
-					? (get_next_installed_ebuild(ebuild, sizeof(ebuild),
-							vdb_dir, &dentry, &cat_dir) != NULL)
-					: (fgets(ebuild, sizeof(ebuild), fp) != NULL)))
-		{
-			FILE *newfp;
-
-			/* filter badly named files, prepare eclass or package name, etc. */
-			if (do_eclass) {
-				if ((p = strrchr(ebuild, '.')) == NULL)
-					continue;
-				if (strcmp(p, ".eclass"))
+			while ((dentry = readdir(eclass_dir)) != NULL) {
+				if (strstr(dentry->d_name, ".eclass") == NULL)
 					continue;
-				if (show_name || (include_atoms != NULL)) {
-					/* cut ".eclass" */
-					*p = '\0';
-					/* and skip "eclass/" */
-					snprintf(name, sizeof(name), "%s", ebuild + 7);
-					/* restore the filepath */
-					*p = '.';
-				}
-			} else {
-				if ((p = strchr(ebuild, '\n')) != NULL)
-					*p = '\0';
-				if (show_name || (include_atoms != NULL)) {
-					size_t l;
-					/* cut ".ebuild" */
-					if (p == NULL)
-						p = ebuild + strlen(ebuild);
-					*(p-7) = '\0';
-					/* cut "/foo/" from "cat/foo/foo-x.y" */
-					if ((p = strchr(ebuild, '/')) == NULL)
-						continue;
-					*(p++) = '\0';
-					/* find head of the ebuild basename */
-					if ((p = strchr(p, '/')) == NULL)
-						continue;
-					/* find	start of the pkg name, break up in two to
-					 * avoid warning about possible truncation (very
-					 * unlikely) */
-					l = snprintf(name, sizeof(name), "%s", ebuild);
-					snprintf(name + l, sizeof(name) - l, "%s", p);
-					/* restore the filepath */
-					*p = '/';
-					*(p + strlen(p)) = '.';
-					ebuild[strlen(ebuild)] = '/';
-				}
-			}
-
-			/* filter the files we grep when there are extra args */
-			if (include_atoms != NULL)
-				if (!qgrep_name_match(name, (argc - optind - 1), include_atoms))
-					continue;
-
-			if ((newfp = fopen(ebuild, "r")) != NULL) {
-				int lineno = 0;
-				char remaining_after_context = 0;
-				count = 0;
-				/* if there have been some matches already, then a
-				 * separator will be needed */
-				need_separator =
-					!status && (num_lines_before || num_lines_after);
-				/* whatever is in the circular buffers list is no more a
-				 * valid context */
-				qgrep_buf_list_invalidate(buf_list);
-
-				/* reading a new line always happen in the next buffer
-				 * of the list */
-				while ((buf_list = buf_list->next) &&
-						fgets(buf_list->buf, sizeof(buf_list->buf), newfp))
-				{
-					lineno++;
-					buf_list->valid = 1;
-
-					/* cleanup EOL */
-					if ((p = strrchr(buf_list->buf, '\n')) != NULL)
-						*p = 0;
-					if ((p = strrchr(buf_list->buf, '\r')) != NULL)
-						*p = 0;
-
-					if (skip_comments) {
-						/* reject comments line ("^[ \t]*#") */
-						p = buf_list->buf;
-						while (*p == ' ' || *p == '\t') p++;
-						if (*p == '#')
-							goto print_after_context;
+				/* filter the files we grep when there are extra args */
+				if (args.include_atoms != NULL) {
+					depend_atom **d;
+					for (d = args.include_atoms; *d != NULL; d++) {
+						if ((*d)->PN != NULL && strncmp(dentry->d_name,
+									(*d)->PN, strlen((*d)->PN)) == 0)
+							break;
 					}
-
-					if (skip_pattern) {
-						/* reject some other lines which match an
-						 * optional pattern */
-						if (!do_regex) {
-							if (strfunc(buf_list->buf, skip_pattern) != NULL)
-								goto print_after_context;
-						} else {
-							if (regexec(&skip_preg, buf_list->buf,
-										0, NULL, 0) == 0)
-								goto print_after_context;
-						}
-					}
-
-					/* four ways to match a line (with/without inversion
-					 * and regexp) */
-					if (!invert_match) {
-						if (do_regex == 0) {
-							if (strfunc(buf_list->buf, argv[optind]) == NULL)
-								goto print_after_context;
-						} else {
-							if (regexec(&preg, buf_list->buf, 0, NULL, 0) != 0)
-								goto print_after_context;
-						}
-					} else {
-						if (do_regex == 0) {
-							if (strfunc(buf_list->buf, argv[optind]) != NULL)
-								goto print_after_context;
-						} else {
-							if (regexec(&preg, buf_list->buf, 0, NULL, 0) == 0)
-								goto print_after_context;
-						}
-					}
-
-					count++;
-					status = 0; /* got a match, exit status should be 0 */
-					if (per_file_output)
+					if (*d == NULL)
 						continue;
-						/* matching files are listed out of this loop */
-
-					if ((need_separator > 0)
-							&& (num_lines_before || num_lines_after))
-						printf("--\n");
-					/* "need_separator" is not a flag, but a counter, so that
-					 * adjacent contextes are not separated */
-					need_separator = 0 - num_lines_before;
-					if (!do_list) {
-						/* print the leading context */
-						qgrep_print_before_context(buf_list,
-								num_lines_before, label,
-								((verbose > 1) ? lineno : -1));
-						/* print matching line */
-						if (invert_match || *RED == '\0')
-							qgrep_print_matching_line_nocolor(buf_list, label,
-								((verbose > 1) ? lineno : -1));
-						else if (do_regex)
-							qgrep_print_matching_line_regcolor(buf_list, label,
-								((verbose > 1) ? lineno : -1), &preg);
-						else
-							qgrep_print_matching_line_strcolor(buf_list, label,
-								((verbose > 1) ? lineno : -1), strfunc,
-								argv[optind]);
-					} else {
-						/* in verbose do_list mode, list the file once
-						 * per match */
-						printf("%s", label);
-						if (verbose > 1)
-							printf(":%d", lineno);
-						putchar('\n');
-					}
-					/* init count down of trailing context lines */
-					remaining_after_context = num_lines_after;
-					continue;
+				}
 
- print_after_context:
-					/* print some trailing context lines when needed */
-					if (!remaining_after_context) {
-						if (!status)
-							/* we're getting closer to the need of a
-							 * separator between current match block and
-							 * the next one */
-							++need_separator;
-					} else {
-						qgrep_print_context_line(buf_list, label,
-								((verbose > 1) ? lineno : -1));
-						--remaining_after_context;
-					}
+				label = NULL;
+				if (args.show_name) {
+					snprintf(name, sizeof(name), "%.*s",
+							(int)(strlen(dentry->d_name) - 7), dentry->d_name);
+					label = name;
+				} else if (args.show_filename) {
+					snprintf(name, sizeof(name), "eclass/%s", dentry->d_name);
+					label = name;
 				}
-				fclose(newfp);
-				if (!per_file_output)
-					continue;
-					/* matches were already displayed, line per line */
-				if (do_count && count) {
-					if (label != NULL)
-						/* -c without -v/-N/-H only outputs
-						 * the matches count of the file */
-						printf("%s:", label);
-					printf("%d\n", count);
-				} else if ((count && !invert_list) || (!count && invert_list))
-					printf("%s\n", label);
-					/* do_list == 1, or we wouldn't be here */
+				status = qgrep_grepat(efd, dentry->d_name, label, &args);
 			}
-		}
-		if (do_eclass)
 			closedir(eclass_dir);
-		else if (!do_installed)
-			fclose(fp);
-
-		if (do_installed)
-			break;
+		} else if (do_installed) {
+			status = q_vdb_foreach_pkg(portroot, portvdb,
+					qgrep_vdb_cb, &args, NULL);
+		} else { /* do_ebuild */
+			status = cache_foreach_pkg(portroot, overlay,
+					qgrep_cache_cb, &args, NULL);
+		}
 	}
 
-	if (do_regex)
-		regfree(&preg);
-	if (do_regex && skip_pattern)
-		regfree(&skip_preg);
-	if (include_atoms != NULL) {
+	if (args.do_regex)
+		regfree(&args.preg);
+	if (args.do_regex && args.skip_pattern)
+		regfree(&args.skip_preg);
+	if (args.include_atoms != NULL) {
 		for (i = 0; i < (argc - optind - 1); i++)
-			if (include_atoms[i] != NULL)
-				atom_implode(include_atoms[i]);
-		free(include_atoms);
+			if (args.include_atoms[i] != NULL)
+				atom_implode(args.include_atoms[i]);
+		free(args.include_atoms);
 	}
-	qgrep_buf_list_free(buf_list);
+	qgrep_buf_list_free(args.buf_list);
 
 	return status;
 }


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-05-13 13:39 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-05-13 13:39 UTC (permalink / raw
  To: gentoo-commits

commit:     966de456d8af3b5102950e608a771f776efdd014
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Mon May 13 13:37:31 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Mon May 13 13:37:31 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=966de456

qlop: support -q to omit timestamps

Allow -q to suppress timestamps and operation markers (<<<, >>> and ***)
such that one can generate a flat list of atoms. A bit awkward, but
combining -q *and* -v will result in atoms with PF (iso PN).

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 TODO.md                       |  5 -----
 man/include/qlop.optdesc.yaml |  4 ++++
 man/qlop.1                    |  2 +-
 qlop.c                        | 24 +++++++++++++++++++++---
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/TODO.md b/TODO.md
index f410f54..ccff6e0 100644
--- a/TODO.md
+++ b/TODO.md
@@ -75,11 +75,6 @@
 
 - make it use standard xarray instead of its own buf\_list
 
-# qlop
-
-- have a mode that doesn't print timestamp (to get just atoms, -v should
-  work)
-
 # qlist
 - have -F for use with -I so one can do things like print SLOT for
   package X

diff --git a/man/include/qlop.optdesc.yaml b/man/include/qlop.optdesc.yaml
index 677c4d2..19f56db 100644
--- a/man/include/qlop.optdesc.yaml
+++ b/man/include/qlop.optdesc.yaml
@@ -42,6 +42,10 @@ current: |
     in order to detect running merges.
 verbose: |
     Print package versions and revisions (PF) instead of package (PN).
+quiet:
+    Omit printing of timestamps and operation symbols, can be used to
+    generate a flat list of atoms, e.g.\ \fB-qml\fR to print the package
+    names merged in the last emerge operation.
 running: |
     Print operations currently in progress.  An ETA is calculated based
     on the average for the operation.  If the elapsed exceeds the

diff --git a/man/qlop.1 b/man/qlop.1
index ae40fa7..6303eee 100644
--- a/man/qlop.1
+++ b/man/qlop.1
@@ -116,7 +116,7 @@ Set the ROOT env var.
 Print package versions and revisions (PF) instead of package (PN).
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
-Tighter output; suppress warnings.
+Omit printing of timestamps and operation symbols, can be used to generate a flat list of atoms, e.g.\ \fB-qml\fR to print the package names merged in the last emerge operation.
 .TP
 \fB\-C\fR, \fB\-\-nocolor\fR
 Don't output color.

diff --git a/qlop.c b/qlop.c
index 5217638..11bbbc3 100644
--- a/qlop.c
+++ b/qlop.c
@@ -506,7 +506,13 @@ static int do_emerge_log(
 					sync_start = 0;  /* reset */
 					continue;
 				}
-				if (flags->do_time) {
+				if (quiet) {
+					printf("%s%s%s%s%s\n",
+							GREEN, p, NORM,
+							flags->do_time ? ": " : "",
+							flags->do_time ?
+								fmt_elapsedtime(flags, elapsed) : "");
+				} else if (flags->do_time) {
 					printf("%s *** %s%s%s: %s\n",
 							fmt_date(flags, sync_start, tstart),
 							GREEN, p, NORM,
@@ -607,7 +613,13 @@ static int do_emerge_log(
 						}
 						break;
 					}
-					if (flags->do_time) {
+					if (quiet && !flags->do_average) {
+						printf("%s%s%s\n",
+								atom_format(afmt, pkgw->atom, 0),
+								flags->do_time ? ": " : "",
+								flags->do_time ?
+									fmt_elapsedtime(flags, elapsed) : "");
+					} else if (flags->do_time) {
 						printf("%s >>> %s: %s\n",
 								fmt_date(flags, pkgw->tbegin, tstart),
 								atom_format(afmt, pkgw->atom, 0),
@@ -706,7 +718,13 @@ static int do_emerge_log(
 						}
 						break;
 					}
-					if (flags->do_time) {
+					if (quiet && !flags->do_average) {
+						printf("%s%s%s\n",
+								atom_format(afmt, pkgw->atom, 0),
+								flags->do_time ? ": " : "",
+								flags->do_time ?
+									fmt_elapsedtime(flags, elapsed) : "");
+					} else if (flags->do_time) {
 						printf("%s <<< %s: %s\n",
 								fmt_date(flags, pkgw->tbegin, tstart),
 								atom_format(afmt, pkgw->atom, 0),


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-05-17 14:35 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-05-17 14:35 UTC (permalink / raw
  To: gentoo-commits

commit:     5531d5c97a27c002abfcc1bd229d0716bba4b2e3
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri May 17 14:34:09 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri May 17 14:34:09 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=5531d5c9

qfile: allow matching basenames to objects by default

one can now do qfile qfile to find app-portage/portage-utils
updated the manpage somewhat

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qfile-01-owners.include     | 30 ++++++-----
 man/include/qfile-02-orphans.include    | 15 +++---
 man/include/qfile-03-ROOT.include       | 20 ++++----
 man/include/qfile-05-collisions.include |  8 +--
 man/include/qfile.desc                  | 23 +++++++++
 man/include/qfile.optdesc.yaml          |  4 ++
 man/qfile.1                             | 88 ++++++++++++++++++++-------------
 qfile.c                                 | 35 ++++++++-----
 8 files changed, 140 insertions(+), 83 deletions(-)

diff --git a/man/include/qfile-01-owners.include b/man/include/qfile-01-owners.include
index a4bdc76..39b1e03 100644
--- a/man/include/qfile-01-owners.include
+++ b/man/include/qfile-01-owners.include
@@ -1,16 +1,14 @@
 .SH "FINDING FILE OWNERS"
 .PP
-This is the default behavior of \fBqfile\fP.  It will list the packages which
-own the files (or directories, or symlinks, or anything else Portage can 
-install) you are querying.  Query items may be file paths or simple file
-names when the \fB\-b\fP option is used.
-By default, output includes packages names and the complete paths to
-the matching files.  If using \fB\-\-exact\fP, versions of the packages will 
-also be shown.  At the contrary, when using \fB\-\-quiet\fP, only package 
-names are listed, without files paths.  Finally, \fB\-\-verbose\fP is similar
-to \fB\-\-exact\fP, but may add a few warnings.  The return status of 
-\fBqfile\fP will be \fI0\fP as soon as an owning package has been found for 
-one of the query items.
+This is the default behavior of \fBqfile\fP.  It will list the packages
+which own the files (or directories, or symlinks, or anything else
+Portage can install) you are querying.  Query items may be file paths or
+simple file names.  By default, output includes packages names and the
+complete paths to the matching files.  If using \fB\-\-verbose\fP,
+versions of the packages will also be shown.  In contrast, when using
+\fB\-\-quiet\fP, only package names are listed, without files paths.
+The return status of \fBqfile\fP will be \fI0\fP as soon as an owning
+package has been found for one of the query items.
 .PP
 Find names of package(s) owning "/bin/bash":
 .nf\fI
@@ -20,17 +18,17 @@ Find names of package(s) owning "/bin/bash":
 .PP
 Find package(s) owning any file named "bash", and show paths of this files:
 .nf\fI
-	$ qfile -b bash
-	app-shells/bash (/bin/bash)
-	app-shells/bash (/etc/bash)
+	$ qfile -d bash
+	app-shells/bash: /bin/bash
+	app-shells/bash: /etc/bash
 .fi
 .PP
 Find packages(s) owning the file named "bash" in the current directory. Also 
 display their exact version:
 .nf\fI
 	$ cd /bin
-	$ qfile -e ./bash
-	app-shells/bash-3.1_p17 (/bin/bash)
+	$ qfile -v ./bash
+	app-shells/bash-3.1_p17: /bin/bash
 .fi
 .PP
 Find the package(s) owning the libraries needed by the Bash binary:

diff --git a/man/include/qfile-02-orphans.include b/man/include/qfile-02-orphans.include
index ca23796..f6754aa 100644
--- a/man/include/qfile-02-orphans.include
+++ b/man/include/qfile-02-orphans.include
@@ -1,13 +1,12 @@
 .SH "FINDING ORPHAN FILES"
 .PP
-\fBqfile\fP can also, with the \fB\-\-orphans\fP option, find files which are 
-not owned by any package.  This behavior is the opposite of the usual file 
-owner search: the output is the list of query items for which no reference has
-been found in your installed packages database.  The \fB\-\-exact\fP option has
-no effect in this mode, whereas \fB\-\-verbose\fP may add a few warning 
-messages.  As for \fB\-\-quiet\fP, it will completly turn off the output, 
-leaving just a silent test command, which returns \fI0\fP if and only if
-there was no orphan in your query items.
+\fBqfile\fP can also, with the \fB\-\-orphans\fP option, find files
+which are not owned by any package.  This behaviour is the opposite of
+the usual file owner search: the output is the list of query items for
+which no reference has been found in your installed packages database.
+As for \fB\-\-quiet\fP, it will completly turn off the output, leaving
+just a silent test command, which returns \fI0\fP if and only if there
+was no orphan in your query items.
 .PP
 Find the orphan libtool files of your system:
 .nf\fI

diff --git a/man/include/qfile-03-ROOT.include b/man/include/qfile-03-ROOT.include
index 61d965d..3bfbe51 100644
--- a/man/include/qfile-03-ROOT.include
+++ b/man/include/qfile-03-ROOT.include
@@ -1,7 +1,7 @@
 .SH "$ROOT HANDLING"
 .PP
 By setting the \fIROOT\fP environment variable, you can force \fBqfile\fP to
-work in the sytem of your choice. This example shows queries for owner of 
+work in the sytem of your choice. This example shows queries for owner of
 "/bin/sh", first on your main system, and then on a system mounted on "/mnt":
 .nf\fI
 	$ qfile -q /bin/sh
@@ -10,25 +10,25 @@ work in the sytem of your choice. This example shows queries for owner of
 	sys-apps/busybox
 .fi
 .PP
-Note that the query item is "/bin/sh" in both commands: by default, what 
-\fBqfile\fP looks for is file paths as they are recorded in the packages 
+Note that the query item is "/bin/sh" in both commands: by default, what
+\fBqfile\fP looks for is file paths as they are recorded in the packages
 database of the target system, and this paths don't include \fI$ROOT\fP.
-If, at the contrary, you want to query files with their current actual 
-paths (including the mount point), you should add the \fB\-\-root\-prefix\fP 
+If, on the contrary, you want to query files with their current actual
+paths (including the mount point), you should add the \fB\-\-root\-prefix\fP
 (\fB\-R\fP) option:
 .nf\fI
 	$ ROOT=/mnt qfile -Rq /mnt/bin/sh
 	sys-apps/busybox
 .fi
 .PP
-The other difference beetween defaults and \fB\-R\fP queries is the output 
-of files paths.  The former doesn't include the \fI$ROOT\fP prefix, and the 
-later does:
+The other difference between defaults and \fB\-R\fP queries is the output
+of files paths.  The former doesn't include the \fI$ROOT\fP prefix, and the
+latter does:
 .nf\fI
 	$ ROOT=/mnt qfile sh
-	sys-apps/busybox (/bin/sh)
+	sys-apps/busybox: /bin/sh
 	$ ROOT=/mnt qfile -R sh
-	sys-apps/busybox (/mnt/bin/sh)
+	sys-apps/busybox: /mnt/bin/sh
 .fi
 .PP
 Sure, the same differences hold when querying for orphan files:

diff --git a/man/include/qfile-05-collisions.include b/man/include/qfile-05-collisions.include
index 1b8672d..dd2c1d8 100644
--- a/man/include/qfile-05-collisions.include
+++ b/man/include/qfile-05-collisions.include
@@ -4,9 +4,9 @@ A last option of \fBqfile\fP is \fB\-\-exclude\fP (\fB\-x\fP), which will makes
 it skip one particular package when doing its files owners search.  This option
 takes one argument, which can be a package name (\fBbash\fP or
 \fBapp\-shells/bash\fP), or a versioned package (\fBbash\-3.2_p9\-r1\fP or
-\fBapp\-shells/bash\-3.2_p9\-r1\fP), or a slotted package (\fBbash:0\fP or 
-\fBapp\-shells/bash:0\fP). It is useful for finding file collisions beetween 
-packages (ie., comparing the contents of one package with the contents of all 
+\fBapp\-shells/bash\-3.2_p9\-r1\fP), or a slotted package (\fBbash:0\fP or
+\fBapp\-shells/bash:0\fP). It is useful for finding file collisions between
+packages (ie.\ comparing the contents of one package with the contents of all
 the others).
 .PP
 For example, the following script will search collisions between all your
@@ -26,7 +26,7 @@ installed packages. Be careful, this will takes time:
 	done
 .fi
 .PP
-An other example is the following script, which can be used to check that a 
+An other example is the following script, which can be used to check that a
 binary package (.tbz2) has no conflict with any of your installed packages,
 but the one it may replace (same name and slot), if any:
 .nf\fI

diff --git a/man/include/qfile.desc b/man/include/qfile.desc
index 08d4bb3..614d8a0 100644
--- a/man/include/qfile.desc
+++ b/man/include/qfile.desc
@@ -2,3 +2,26 @@
 packages must be installed, thus the search is for any file on the
 filesystem, to what package that file belongs.  It allows to identify
 which package installed a certain file.
+.P
+The arguments to \fIqfile\fR can be absolute or relative paths and
+individual files.  By default arguments are interpreted as follows:
+.RS
+.IP "absolute path"
+The path is matched against directories, symlinks and objects.
+.IP "relative path"
+The path is resolved against the current directory, and after that
+matched like an absolute path.
+.IP "-d option in use"
+The basename (last component) of the argument path is matched to any
+directory, symlink or object whose basename matches.  This effectively
+means it matches directories as well as symlinks and objects unlike when
+\fB-d\fR is not given and a basename is given as argument.
+.IP basename
+The basename is first attempted to be located in the current directory.
+If an object exists by that name, it is matched like an absolute path.
+If no such object exists, the name is matched against the basename of
+any symlink or object.  For matching directories, use \fB-d\fR.
+.RE
+.P
+After version \fB0.74\fR of portage-utils, the \fB-b\fR option was
+renamed to \fB-d\fR.

diff --git a/man/include/qfile.optdesc.yaml b/man/include/qfile.optdesc.yaml
index cb1cd7a..66ee885 100644
--- a/man/include/qfile.optdesc.yaml
+++ b/man/include/qfile.optdesc.yaml
@@ -5,3 +5,7 @@ verbose: |
 quiet: |
     Don't print matching file for matches, just the package.  Don't
     report about orphan files.
+dir: |
+    Only consider basename of argument and also match directories, this
+    option makes qlist ignore any path component given in the arguments
+    if present.

diff --git a/man/qfile.1 b/man/qfile.1
index 1440bd7..8d5b7dc 100644
--- a/man/qfile.1
+++ b/man/qfile.1
@@ -10,6 +10,29 @@ qfile \- list all pkgs owning files
 packages must be installed, thus the search is for any file on the
 filesystem, to what package that file belongs.  It allows to identify
 which package installed a certain file.
+.P
+The arguments to \fIqfile\fR can be absolute or relative paths and
+individual files.  By default arguments are interpreted as follows:
+.RS
+.IP "absolute path"
+The path is matched against directories, symlinks and objects.
+.IP "relative path"
+The path is resolved against the current directory, and after that
+matched like an absolute path.
+.IP "-d option in use"
+The basename (last component) of the argument path is matched to any
+directory, symlink or object whose basename matches.  This effectively
+means it matches directories as well as symlinks and objects unlike when
+\fB-d\fR is not given and a basename is given as argument.
+.IP basename
+The basename is first attempted to be located in the current directory.
+If an object exists by that name, it is matched like an absolute path.
+If no such object exists, the name is matched against the basename of
+any symlink or object.  For matching directories, use \fB-d\fR.
+.RE
+.P
+After version \fB0.74\fR of portage-utils, the \fB-b\fR option was
+renamed to \fB-d\fR.
 .SH OPTIONS
 .TP
 \fB\-S\fR, \fB\-\-slots\fR
@@ -18,8 +41,10 @@ Display installed packages with slots.
 \fB\-R\fR, \fB\-\-root\-prefix\fR
 Assume arguments are already prefixed by $ROOT.
 .TP
-\fB\-b\fR, \fB\-\-basename\fR
-Match any component of the path.
+\fB\-d\fR, \fB\-\-dir\fR
+Only consider basename of argument and also match directories, this
+option makes qlist ignore any path component given in the arguments
+if present.
 .TP
 \fB\-o\fR, \fB\-\-orphans\fR
 List orphan files.
@@ -49,17 +74,15 @@ Print this help and exit.
 Print version and exit.
 .SH "FINDING FILE OWNERS"
 .PP
-This is the default behavior of \fBqfile\fP.  It will list the packages which
-own the files (or directories, or symlinks, or anything else Portage can
-install) you are querying.  Query items may be file paths or simple file
-names when the \fB\-b\fP option is used.
-By default, output includes packages names and the complete paths to
-the matching files.  If using \fB\-\-exact\fP, versions of the packages will
-also be shown.  At the contrary, when using \fB\-\-quiet\fP, only package
-names are listed, without files paths.  Finally, \fB\-\-verbose\fP is similar
-to \fB\-\-exact\fP, but may add a few warnings.  The return status of
-\fBqfile\fP will be \fI0\fP as soon as an owning package has been found for
-one of the query items.
+This is the default behavior of \fBqfile\fP.  It will list the packages
+which own the files (or directories, or symlinks, or anything else
+Portage can install) you are querying.  Query items may be file paths or
+simple file names.  By default, output includes packages names and the
+complete paths to the matching files.  If using \fB\-\-verbose\fP,
+versions of the packages will also be shown.  In contrast, when using
+\fB\-\-quiet\fP, only package names are listed, without files paths.
+The return status of \fBqfile\fP will be \fI0\fP as soon as an owning
+package has been found for one of the query items.
 .PP
 Find names of package(s) owning "/bin/bash":
 .nf\fI
@@ -69,17 +92,17 @@ Find names of package(s) owning "/bin/bash":
 .PP
 Find package(s) owning any file named "bash", and show paths of this files:
 .nf\fI
-	$ qfile -b bash
-	app-shells/bash (/bin/bash)
-	app-shells/bash (/etc/bash)
+	$ qfile -d bash
+	app-shells/bash: /bin/bash
+	app-shells/bash: /etc/bash
 .fi
 .PP
 Find packages(s) owning the file named "bash" in the current directory. Also
 display their exact version:
 .nf\fI
 	$ cd /bin
-	$ qfile -e ./bash
-	app-shells/bash-3.1_p17 (/bin/bash)
+	$ qfile -v ./bash
+	app-shells/bash-3.1_p17: /bin/bash
 .fi
 .PP
 Find the package(s) owning the libraries needed by the Bash binary:
@@ -91,14 +114,13 @@ Find the package(s) owning the libraries needed by the Bash binary:
 .fi
 .SH "FINDING ORPHAN FILES"
 .PP
-\fBqfile\fP can also, with the \fB\-\-orphans\fP option, find files which are
-not owned by any package.  This behavior is the opposite of the usual file
-owner search: the output is the list of query items for which no reference has
-been found in your installed packages database.  The \fB\-\-exact\fP option has
-no effect in this mode, whereas \fB\-\-verbose\fP may add a few warning
-messages.  As for \fB\-\-quiet\fP, it will completly turn off the output,
-leaving just a silent test command, which returns \fI0\fP if and only if
-there was no orphan in your query items.
+\fBqfile\fP can also, with the \fB\-\-orphans\fP option, find files
+which are not owned by any package.  This behaviour is the opposite of
+the usual file owner search: the output is the list of query items for
+which no reference has been found in your installed packages database.
+As for \fB\-\-quiet\fP, it will completly turn off the output, leaving
+just a silent test command, which returns \fI0\fP if and only if there
+was no orphan in your query items.
 .PP
 Find the orphan libtool files of your system:
 .nf\fI
@@ -128,7 +150,7 @@ work in the sytem of your choice. This example shows queries for owner of
 Note that the query item is "/bin/sh" in both commands: by default, what
 \fBqfile\fP looks for is file paths as they are recorded in the packages
 database of the target system, and this paths don't include \fI$ROOT\fP.
-If, at the contrary, you want to query files with their current actual
+If, on the contrary, you want to query files with their current actual
 paths (including the mount point), you should add the \fB\-\-root\-prefix\fP
 (\fB\-R\fP) option:
 .nf\fI
@@ -136,14 +158,14 @@ paths (including the mount point), you should add the \fB\-\-root\-prefix\fP
 	sys-apps/busybox
 .fi
 .PP
-The other difference beetween defaults and \fB\-R\fP queries is the output
+The other difference between defaults and \fB\-R\fP queries is the output
 of files paths.  The former doesn't include the \fI$ROOT\fP prefix, and the
-later does:
+latter does:
 .nf\fI
 	$ ROOT=/mnt qfile sh
-	sys-apps/busybox (/bin/sh)
+	sys-apps/busybox: /bin/sh
 	$ ROOT=/mnt qfile -R sh
-	sys-apps/busybox (/mnt/bin/sh)
+	sys-apps/busybox: /mnt/bin/sh
 .fi
 .PP
 Sure, the same differences hold when querying for orphan files:
@@ -160,8 +182,8 @@ it skip one particular package when doing its files owners search.  This option
 takes one argument, which can be a package name (\fBbash\fP or
 \fBapp\-shells/bash\fP), or a versioned package (\fBbash\-3.2_p9\-r1\fP or
 \fBapp\-shells/bash\-3.2_p9\-r1\fP), or a slotted package (\fBbash:0\fP or
-\fBapp\-shells/bash:0\fP). It is useful for finding file collisions beetween
-packages (ie., comparing the contents of one package with the contents of all
+\fBapp\-shells/bash:0\fP). It is useful for finding file collisions between
+packages (ie.\ comparing the contents of one package with the contents of all
 the others).
 .PP
 For example, the following script will search collisions between all your

diff --git a/qfile.c b/qfile.c
index 5a9f7c5..d321a59 100644
--- a/qfile.c
+++ b/qfile.c
@@ -20,11 +20,11 @@
 #include "rmspace.h"
 #include "tree.h"
 
-#define QFILE_FLAGS "boRx:S" COMMON_FLAGS
+#define QFILE_FLAGS "doRx:S" COMMON_FLAGS
 static struct option const qfile_long_opts[] = {
 	{"slots",       no_argument, NULL, 'S'},
 	{"root-prefix", no_argument, NULL, 'R'},
-	{"basename",    no_argument, NULL, 'b'},
+	{"dir",         no_argument, NULL, 'd'},
 	{"orphans",     no_argument, NULL, 'o'},
 	{"exclude",      a_argument, NULL, 'x'},
 	COMMON_LONG_OPTS
@@ -32,7 +32,7 @@ static struct option const qfile_long_opts[] = {
 static const char * const qfile_opts_help[] = {
 	"Display installed packages with slots",
 	"Assume arguments are already prefixed by $ROOT",
-	"Match any component of the path",
+	"Also match directories for single component arguments",
 	"List orphan files",
 	"Don't look in package <arg> (used with --orphans)",
 	COMMON_OPTS_HELP
@@ -191,14 +191,25 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 					/* real_dir_name == realpath(dirname(CONTENTS)) */
 					path_ok = true;
 				}
-			} else if (state->basename) {
+			}
+
+			if (!path_ok && state->basename) {
 				path_ok = true;
-			} else if (state->pwd && dir_names[i] == NULL) {
+			}
+
+			if (!path_ok && state->pwd && dir_names[i] == NULL) {
 				/* try to match file in current directory */
 				if (strncmp(e->name, state->pwd, dirname_len) == 0 &&
 						state->pwd[dirname_len] == '\0')
 					path_ok = true;
 			}
+
+			if (!path_ok && dir_names[i] == NULL && real_dir_names[i] == NULL) {
+				/* try basename match */
+				if (e->type != CONTENTS_DIR)
+					path_ok = true;
+			}
+
 			if (!path_ok)
 				continue;
 
@@ -401,15 +412,16 @@ int qfile_main(int argc, char **argv)
 	while ((i = GETOPT_LONG(QFILE, qfile, "")) != -1) {
 		switch (i) {
 			COMMON_GETOPTS_CASES(qfile)
-			case 'S': state.slotted = true; break;
-			case 'b': state.basename = true; break;
-			case 'o': state.orphans = true; break;
-			case 'R': state.assume_root_prefix = true; break;
+			case 'S': state.slotted = true;             break;
+			case 'd': state.basename = true;            break;
+			case 'o': state.orphans = true;             break;
+			case 'R': state.assume_root_prefix = true;  break;
 			case 'x':
 				if (state.exclude_pkg)
 					err("--exclude can only be used once.");
 				state.exclude_pkg = xstrdup(optarg);
-				if ((state.exclude_slot = strchr(state.exclude_pkg, ':')) != NULL)
+				state.exclude_slot = strchr(state.exclude_pkg, ':');
+				if (state.exclude_slot != NULL)
 					*state.exclude_slot++ = '\0';
 				state.exclude_atom = atom_explode(optarg);
 				if (!state.exclude_atom)
@@ -426,8 +438,7 @@ int qfile_main(int argc, char **argv)
 	state.buf = xmalloc(state.buflen);
 	if (state.assume_root_prefix) {
 		/* Get a copy of $ROOT, with no trailing slash
-		 * (this one is just for qfile(...) output)
-		 */
+		 * (this one is just for qfile(...) output) */
 		size_t lastc = strlen(portroot) - 1;
 		state.root = xstrdup(portroot);
 		if (state.root[lastc] == '/')


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-06-09  9:53 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-06-09  9:53 UTC (permalink / raw
  To: gentoo-commits

commit:     c0b88fe2b32679f1548a280d906b82b1651cd804
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Jun  9 09:51:26 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Jun  9 09:51:26 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c0b88fe2

qgrep: print filename for matches by default, fix atom_compare call

remove very similar vdb callback in favour of generic tree one
format atoms using atom_format for consistency and ease of use
retrieve full atoms when SLOT or REPO matches are attempted

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qgrep.optdesc.yaml |   2 +-
 man/qgrep.1                    |  41 ++++++++---------
 qgrep.c                        | 100 +++++++++++------------------------------
 3 files changed, 47 insertions(+), 96 deletions(-)

diff --git a/man/include/qgrep.optdesc.yaml b/man/include/qgrep.optdesc.yaml
index ad3874d..9716bf0 100644
--- a/man/include/qgrep.optdesc.yaml
+++ b/man/include/qgrep.optdesc.yaml
@@ -1,4 +1,4 @@
 verbose: |
     Prefix each matching line with filename (like \fB-H\fR).  When this
     option is given multiple times, also linenumbers are printed.
-quiet: Ignored for compatibility with other qapplets.
+quiet: Do not prefix each match with filename.

diff --git a/man/qgrep.1 b/man/qgrep.1
index 180b5dd..6701061 100644
--- a/man/qgrep.1
+++ b/man/qgrep.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH qgrep "1" "May 2019" "Gentoo Foundation" "qgrep"
+.TH qgrep "1" "Jun 2019" "Gentoo Foundation" "qgrep"
 .SH NAME
 qgrep \- grep in ebuilds
 .SH SYNOPSIS
@@ -20,66 +20,63 @@ Select non-matching lines.
 \fB\-i\fR, \fB\-\-ignore\-case\fR
 Ignore case distinctions.
 .TP
-\fB\-H\fR, \fB\-\-with\-filename\fR
-Print the filename for each match.
-.TP
 \fB\-N\fR, \fB\-\-with\-name\fR
-Print the package or eclass name for each match.
+Print the filename for each match.
 .TP
 \fB\-c\fR, \fB\-\-count\fR
-Only print a count of matching lines per FILE.
+Print the package or eclass name for each match.
 .TP
 \fB\-l\fR, \fB\-\-list\fR
-Only print FILE names containing matches.
+Only print a count of matching lines per FILE.
 .TP
 \fB\-L\fR, \fB\-\-invert\-list\fR
-Only print FILE names containing no match.
+Only print FILE names containing matches.
 .TP
 \fB\-e\fR, \fB\-\-regexp\fR
-Use PATTERN as a regular expression.
+Only print FILE names containing no match.
 .TP
 \fB\-x\fR, \fB\-\-extended\fR
-Use PATTERN as an extended regular expression.
+Use PATTERN as a regular expression.
 .TP
 \fB\-J\fR, \fB\-\-installed\fR
-Search in installed ebuilds instead of the tree.
+Use PATTERN as an extended regular expression.
 .TP
 \fB\-E\fR, \fB\-\-eclass\fR
-Search in eclasses instead of ebuilds.
+Search in installed ebuilds instead of the tree.
 .TP
 \fB\-s\fR, \fB\-\-skip\-comments\fR
-Skip comments lines.
+Search in eclasses instead of ebuilds.
 .TP
 \fB\-R\fR, \fB\-\-repo\fR
-Print source repository name for each match (implies -N).
+Skip comments lines.
 .TP
 \fB\-S\fR \fI<arg>\fR, \fB\-\-skip\fR \fI<arg>\fR
-Skip lines matching <arg>.
+Print source repository name for each match (implies -N).
 .TP
 \fB\-B\fR \fI<arg>\fR, \fB\-\-before\fR \fI<arg>\fR
-Print <arg> lines of leading context.
+Skip lines matching <arg>.
 .TP
 \fB\-A\fR \fI<arg>\fR, \fB\-\-after\fR \fI<arg>\fR
-Print <arg> lines of trailing context.
+Print <arg> lines of leading context.
 .TP
 \fB\-\-root\fR \fI<arg>\fR
-Set the ROOT env var.
+Print <arg> lines of trailing context.
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
 Prefix each matching line with filename (like \fB-H\fR).  When this
 option is given multiple times, also linenumbers are printed.
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
-Ignored for compatibility with other qapplets.
+Do not prefix each match with filename.
 .TP
 \fB\-C\fR, \fB\-\-nocolor\fR
-Don't output color.
+Tighter output; suppress warnings.
 .TP
 \fB\-h\fR, \fB\-\-help\fR
-Print this help and exit.
+Don't output color.
 .TP
 \fB\-V\fR, \fB\-\-version\fR
-Print version and exit.
+Print this help and exit.
 
 .SH "REPORTING BUGS"
 Please report bugs via http://bugs.gentoo.org/

diff --git a/qgrep.c b/qgrep.c
index dff959b..058026e 100644
--- a/qgrep.c
+++ b/qgrep.c
@@ -24,11 +24,10 @@
 #include "xchdir.h"
 #include "xregex.h"
 
-#define QGREP_FLAGS "IiHNclLexJEsRS:B:A:" COMMON_FLAGS
+#define QGREP_FLAGS "IiNclLexJEsRS:B:A:" COMMON_FLAGS
 static struct option const qgrep_long_opts[] = {
 	{"invert-match",  no_argument, NULL, 'I'},
 	{"ignore-case",   no_argument, NULL, 'i'},
-	{"with-filename", no_argument, NULL, 'H'},
 	{"with-name",     no_argument, NULL, 'N'},
 	{"count",         no_argument, NULL, 'c'},
 	{"list",          no_argument, NULL, 'l'},
@@ -398,6 +397,8 @@ qgrep_cache_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	if (data->include_atoms != NULL) {
 		depend_atom **d;
 		for (d = data->include_atoms; *d != NULL; d++) {
+			if ((*d)->SLOT != NULL || (*d)->REPO != NULL)
+				patom = tree_get_atom(pkg_ctx, true);
 			if (atom_compare(patom, *d) == EQUAL)
 				break;
 		}
@@ -409,6 +410,8 @@ qgrep_cache_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	cctx = (tree_ctx *)(pkg_ctx->cat_ctx->ctx);
 	if (cctx->cachetype == CACHE_EBUILD) {
 		pfd = cctx->tree_fd;
+	} else if (cctx->cachetype == CACHE_VDB) {
+		pfd = openat(cctx->portroot_fd, data->portdir, O_RDONLY|O_CLOEXEC);
 	} else {
 		pfd = openat(cctx->tree_fd, "../..", O_RDONLY|O_CLOEXEC);
 	}
@@ -419,11 +422,9 @@ qgrep_cache_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 
 	label = NULL;
 	if (data->show_name) {
-		/* this is a super-optimisation, should get it from the full atom */
-		char *repo = data->show_repo ? cctx->repo : NULL;
-		snprintf(name, sizeof(name), "%s%s/%s%s%s%s%s%s",
-				BOLD, patom->CATEGORY, BLUE, patom->P, GREEN,
-				repo ? "::" : "", repo ? repo : "", NORM);
+		if (data->show_repo)
+			patom = tree_get_atom(pkg_ctx, true);
+		atom_format_r(name, sizeof(name), "%[CATEGORY]%[P]%[REPO]", patom, 0);
 		label = name;
 	} else if (data->show_filename) {
 		label = buf;
@@ -435,55 +436,6 @@ qgrep_cache_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	return ret;
 }
 
-static int
-qgrep_vdb_cb(tree_pkg_ctx *pkg_ctx, void *priv)
-{
-	struct qgrep_grepargs *data = (struct qgrep_grepargs *)priv;
-	char buf[_Q_PATH_MAX];
-	char name[_Q_PATH_MAX];
-	char *label;
-	depend_atom *patom = NULL;
-	int ret;
-	int pfd;
-
-	patom = tree_get_atom(pkg_ctx, false);
-	if (patom == NULL)
-		return EXIT_FAILURE;
-
-	if (data->include_atoms != NULL) {
-		depend_atom **d;
-		for (d = data->include_atoms; *d != NULL; d++) {
-			if (atom_compare(patom, *d) == EQUAL)
-				break;
-		}
-		if (*d == NULL) {
-			atom_implode(patom);
-			return EXIT_FAILURE;
-		}
-	}
-
-	/* get path to portdir */
-	pfd = openat(pkg_ctx->cat_ctx->ctx->portroot_fd,
-			data->portdir, O_RDONLY|O_CLOEXEC);
-
-	/* cat/pkg/pkg-ver.ebuild */
-	snprintf(buf, sizeof(buf), "%s/%s/%s.ebuild",
-			patom->CATEGORY, patom->PN, patom->P);
-
-	label = NULL;
-	if (data->show_name) {
-		snprintf(name, sizeof(name), "%s%s/%s%s%s",
-				BOLD, patom->CATEGORY, BLUE, patom->P, NORM);
-		label = name;
-	} else if (data->show_filename) {
-		label = buf;
-	}
-
-	ret = qgrep_grepat(pfd, buf, label, data);
-
-	return ret;
-}
-
 int qgrep_main(int argc, char **argv)
 {
 	int i;
@@ -499,14 +451,14 @@ int qgrep_main(int argc, char **argv)
 	char *overlay;
 
 	struct qgrep_grepargs args = {
-		.do_count = 0,
-		.do_regex = 0,
-		.do_list = 0,
-		.show_filename = 0,
-		.show_name = 0,
-		.skip_comments = 0,
-		.invert_list = 0,
-		.invert_match = 0,
+		.do_count = false,
+		.do_regex = false,
+		.do_list = false,
+		.show_filename = true,
+		.show_name = false,
+		.skip_comments = false,
+		.invert_list = false,
+		.invert_match = false,
 		.skip_pattern = NULL,
 		.num_lines_before = 0,
 		.num_lines_after = 0,
@@ -536,8 +488,8 @@ int qgrep_main(int argc, char **argv)
 			break;
 		case 'J': do_installed = true;                    break;
 		case 'E': do_eclass = true;                       break;
-		case 'H': args.show_filename = true;              break;
-		case 'N': args.show_name = true;                  break;
+		case 'N': args.show_name = true;
+				  args.show_filename = false;             break;
 		case 's': args.skip_comments = true;              break;
 		case 'R': args.show_repo = args.show_name = true; break;
 		case 'S': args.skip_pattern = optarg;             break;
@@ -562,6 +514,9 @@ int qgrep_main(int argc, char **argv)
 	if (argc == optind)
 		qgrep_usage(EXIT_FAILURE);
 
+	if (quiet)
+		args.show_filename = args.show_name = false;
+
 	if (args.do_list && args.do_count) {
 		warn("%s and --count are incompatible options. The former wins.",
 				(args.invert_list ? "--invert-list" : "--list"));
@@ -677,14 +632,13 @@ int qgrep_main(int argc, char **argv)
 				status = qgrep_grepat(efd, dentry->d_name, label, &args);
 			}
 			closedir(eclass_dir);
-		} else if (do_installed) {
-			tree_ctx *t = tree_open_vdb(portroot, portvdb);
-			if (t != NULL) {
-				status = tree_foreach_pkg_fast(t, qgrep_vdb_cb, &args, NULL);
-				tree_close(t);
+		} else { /* do_ebuild || do_installed */
+			tree_ctx *t;
+			if (do_installed) {
+				t = tree_open_vdb(portroot, portvdb);
+			} else {
+				t = tree_open(portroot, overlay);
 			}
-		} else { /* do_ebuild */
-			tree_ctx *t = tree_open(portroot, overlay);
 			if (t != NULL) {
 				status = tree_foreach_pkg_fast(t, qgrep_cache_cb, &args, NULL);
 				tree_close(t);


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-07-18 18:36 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-07-18 18:36 UTC (permalink / raw
  To: gentoo-commits

commit:     94ca500baf225994b88f750262c0895553c70a8a
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Thu Jul 18 18:34:19 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Thu Jul 18 18:34:19 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=94ca500b

qlop: enhance running time indicator

Fix elapsed time mode (-t) when using -r displaying the elapsed time
also as the ETA.  When using -v, display what ETA is being used (average
or longest run).

Also, better document which flags can be combined with -r.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qlop.optdesc.yaml |  7 +++++--
 man/qlop.1                    |  7 +++++--
 qlop.c                        | 47 +++++++++++++++++++++++++------------------
 3 files changed, 37 insertions(+), 24 deletions(-)

diff --git a/man/include/qlop.optdesc.yaml b/man/include/qlop.optdesc.yaml
index 19f56db..463a19d 100644
--- a/man/include/qlop.optdesc.yaml
+++ b/man/include/qlop.optdesc.yaml
@@ -50,5 +50,8 @@ running: |
     Print operations currently in progress.  An ETA is calculated based
     on the average for the operation.  If the elapsed exceeds the
     average, the ETA is calculated against the longest time observed for
-    the operation.  If the elapsed time exceeds this too, or no previous
-    occurrences for the operation exist, \fIunknown\fR is printed.
+    the operation.  The \fB-v\fR flag will display which mode is
+    currently used.  If the elapsed time also exceeds the longest time
+    observed, or no previous occurrences for the operation exist,
+    \fIunknown\fR is printed.  When combined with \fB-t\fR the
+    elapsed time is also displayed.

diff --git a/man/qlop.1 b/man/qlop.1
index 10eaa27..909ebdc 100644
--- a/man/qlop.1
+++ b/man/qlop.1
@@ -72,8 +72,11 @@ Report time at which the operation finished (iso started).
 Print operations currently in progress.  An ETA is calculated based
 on the average for the operation.  If the elapsed exceeds the
 average, the ETA is calculated against the longest time observed for
-the operation.  If the elapsed time exceeds this too, or no previous
-occurrences for the operation exist, \fIunknown\fR is printed.
+the operation.  The \fB-v\fR flag will display which mode is
+currently used.  If the elapsed time also exceeds the longest time
+observed, or no previous occurrences for the operation exist,
+\fIunknown\fR is printed.  When combined with \fB-t\fR the
+elapsed time is also displayed.
 .TP
 \fB\-d\fR \fI<arg>\fR, \fB\-\-date\fR \fI<arg>\fR
 Limit the selection of packages to the date given, or to the range

diff --git a/qlop.c b/qlop.c
index e20c97b..fce0f69 100644
--- a/qlop.c
+++ b/qlop.c
@@ -773,14 +773,17 @@ static int do_emerge_log(
 		array_for_each(merge_matches, i, pkgw) {
 			size_t j;
 			time_t maxtime = 0;
+			bool isMax = false;
 
 			elapsed = tstart - pkgw->tbegin;
 			pkg = NULL;
 			array_for_each(merge_averages, j, pkg) {
 				if (atom_compare(pkg->atom, pkgw->atom) == EQUAL) {
 					maxtime = pkg->time / pkg->cnt;
-					if (elapsed >= maxtime)
+					if (elapsed >= maxtime) {
 						maxtime = elapsed >= pkg->tbegin ? 0 : pkg->tbegin;
+						isMax = true;
+					}
 					break;
 				}
 				pkg = NULL;
@@ -797,52 +800,56 @@ static int do_emerge_log(
 			}
 
 			if (flags->do_time) {
-				printf("%s >>> %s: %s...%s ETA: %s\n",
+				printf("%s >>> %s: %s",
 						fmt_date(flags, pkgw->tbegin, 0),
 						atom_format(flags->fmt, pkgw->atom),
-						fmt_elapsedtime(flags, elapsed),
-						p == NULL ? "" : p,
-						maxtime == 0 ? "unknown" :
-							fmt_elapsedtime(flags, maxtime - elapsed));
+						fmt_elapsedtime(flags, elapsed));
 			} else {
-				printf("%s >>> %s...%s ETA: %s\n",
+				printf("%s >>> %s",
 						fmt_date(flags, pkgw->tbegin, 0),
-						atom_format(flags->fmt, pkgw->atom),
-						p == NULL ? "" : p,
-						maxtime == 0 ? "unknown" :
-							fmt_elapsedtime(flags, maxtime - elapsed));
+						atom_format(flags->fmt, pkgw->atom));
 			}
+			printf("...%s ETA: %s%s\n",
+					p == NULL ? "" : p,
+					maxtime == 0 ? "unknown" :
+						fmt_elapsedtime(flags, maxtime - elapsed),
+					maxtime > 0 && verbose ?
+						isMax ? " (longest run)" : " (average run)" : "");
 		}
 		array_for_each(unmerge_matches, i, pkgw) {
 			size_t j;
 			time_t maxtime = 0;
+			bool isMax = false;
 
 			elapsed = tstart - pkgw->tbegin;
 			pkg = NULL;
 			array_for_each(unmerge_averages, j, pkg) {
 				if (atom_compare(pkg->atom, pkgw->atom) == EQUAL) {
 					maxtime = pkg->time / pkg->cnt;
-					if (elapsed >= maxtime)
+					if (elapsed >= maxtime) {
 						maxtime = elapsed >= pkg->tbegin ? 0 : pkg->tbegin;
+						isMax = true;
+					}
 					break;
 				}
 				pkg = NULL;
 			}
 
 			if (flags->do_time) {
-				printf("%s <<< %s: %s... ETA: %s\n",
+				printf("%s <<< %s: %s",
 						fmt_date(flags, pkgw->tbegin, 0),
 						atom_format(flags->fmt, pkgw->atom),
-						fmt_elapsedtime(flags, elapsed),
-						maxtime == 0 ? "unknown" :
-							fmt_elapsedtime(flags, maxtime - elapsed));
+						fmt_elapsedtime(flags, elapsed));
 			} else {
-				printf("%s <<< %s... ETA: %s\n",
+				printf("%s <<< %s",
 						fmt_date(flags, pkgw->tbegin, 0),
-						atom_format(flags->fmt, pkgw->atom),
-						maxtime == 0 ? "unknown" :
-							fmt_elapsedtime(flags, maxtime - elapsed));
+						atom_format(flags->fmt, pkgw->atom));
 			}
+			printf("... ETA: %s%s\n",
+					maxtime == 0 ? "unknown" :
+					fmt_elapsedtime(flags, maxtime - elapsed),
+					maxtime > 0 && verbose ?
+						isMax ? " (longest run)" : " (average run)" : "");
 		}
 	} else if (flags->do_average) {
 		size_t total_merges = 0;


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2019-12-27 19:16 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2019-12-27 19:16 UTC (permalink / raw
  To: gentoo-commits

commit:     1038786d92a885dece9cc82588e88d8367a0fda2
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri Dec 27 19:14:44 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri Dec 27 19:14:44 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=1038786d

qkeyword: apply profile masks to -S/-T results

Technically, this should be enough to implement the Puppet provider for
Gentoo.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qkeyword-01-latest-testing.include | 23 ++++++++
 man/include/qkeyword.desc                      | 10 +++-
 man/qkeyword.1                                 | 34 ++++++++++--
 qkeyword.c                                     | 73 +++++++++++++++++++++-----
 4 files changed, 121 insertions(+), 19 deletions(-)

diff --git a/man/include/qkeyword-01-latest-testing.include b/man/include/qkeyword-01-latest-testing.include
new file mode 100644
index 0000000..1c2fde5
--- /dev/null
+++ b/man/include/qkeyword-01-latest-testing.include
@@ -0,0 +1,23 @@
+.SH "RETRIEVING LATEST TESTING VERSION AVAILABLE"
+.PP
+To retrieve the latest available version in the ebuild tree marked as
+testing for the given ARCH, can be done with a combination of flags,
+mostly to restrict the search.  For instance, to find the latest version
+of \fIsys-devel/gcc\fR available, one could use:
+.nf
+$ qkeyword -p sys-devel/gcc -T
+sys-devel/gcc-8.3.0
+.fi
+It may be that there is a newer version available, but masked for the
+configured profile (via package.mask).  Using \fB-v\fR will inform about
+this scenario happening:
+.nf
+$ qkeyword -p dev-vcs/cvs -Tv
+masked by =dev-vcs/cvs-1.12.12*: dev-vcs/cvs-1.12.12-r12
+.fi
+Unrelated, but to locate the mask given, use verbose mode on \fIq\fR's
+mask listing:
+.nf
+$ q -mv dev-vcs/cvs
+=dev-vcs/cvs-1.12.12* [/repo/gentoo/profiles/prefix/sunos/solaris/package.mask]
+.fi

diff --git a/man/include/qkeyword.desc b/man/include/qkeyword.desc
index b7a863c..adc55ea 100644
--- a/man/include/qkeyword.desc
+++ b/man/include/qkeyword.desc
@@ -1,5 +1,5 @@
-\fIqkeyword\fR allows various searches based on KEYWORDS aimed at Gentoo
-developers.  Various modes allow to query which packages would be
+\fIqkeyword\fR allows various searches based on KEYWORDS.  Some uses are
+aimed at Gentoo developers, to allow querying which packages would be
 available, or are candidate for keywording.
 .P
 By default, the entire tree is traversed.  Since this process can be
@@ -12,3 +12,9 @@ as package in one go.  The \fB-m\fR maintainer match, while reducing the
 resulting set, is likely to slow down the query processing since the
 metadata.xml file has to be read for each package examined.  It is best
 used in combination with \fB-p\fR or \fB-c\fR.
+.P
+\fIqkeyword\fR uses the keyword found in the configured profile (ARCH)
+for its queries.  This keyword can be overridden by giving the desired
+keyword as argument.  Note that this does not change the profile in use,
+which most notably can result in incorrect masks being applied for the
+\fB-T\fR and \fB-S\fR options.

diff --git a/man/qkeyword.1 b/man/qkeyword.1
index 34beb18..5a26218 100644
--- a/man/qkeyword.1
+++ b/man/qkeyword.1
@@ -6,8 +6,8 @@ qkeyword \- list packages based on keywords
 .B qkeyword
 \fI[opts] <action> <args>\fR
 .SH DESCRIPTION
-\fIqkeyword\fR allows various searches based on KEYWORDS aimed at Gentoo
-developers.  Various modes allow to query which packages would be
+\fIqkeyword\fR allows various searches based on KEYWORDS.  Some uses are
+aimed at Gentoo developers, to allow querying which packages would be
 available, or are candidate for keywording.
 .P
 By default, the entire tree is traversed.  Since this process can be
@@ -20,6 +20,12 @@ as package in one go.  The \fB-m\fR maintainer match, while reducing the
 resulting set, is likely to slow down the query processing since the
 metadata.xml file has to be read for each package examined.  It is best
 used in combination with \fB-p\fR or \fB-c\fR.
+.P
+\fIqkeyword\fR uses the keyword found in the configured profile (ARCH)
+for its queries.  This keyword can be overridden by giving the desired
+keyword as argument.  Note that this does not change the profile in use,
+which most notably can result in incorrect masks being applied for the
+\fB-T\fR and \fB-S\fR options.
 .SH OPTIONS
 .TP
 \fB\-p\fR \fI<arg>\fR, \fB\-\-matchpkg\fR \fI<arg>\fR
@@ -75,7 +81,29 @@ Print this help and exit.
 .TP
 \fB\-V\fR, \fB\-\-version\fR
 Print version and exit.
-
+.SH "RETRIEVING LATEST TESTING VERSION AVAILABLE"
+.PP
+To retrieve the latest available version in the ebuild tree marked as
+testing for the given ARCH, can be done with a combination of flags,
+mostly to restrict the search.  For instance, to find the latest version
+of \fIsys-devel/gcc\fR available, one could use:
+.nf
+$ qkeyword -p sys-devel/gcc -T
+sys-devel/gcc-8.3.0
+.fi
+It may be that there is a newer version available, but masked for the
+configured profile (via package.mask).  Using \fB-v\fR will inform about
+this scenario happening:
+.nf
+$ qkeyword -p dev-vcs/cvs -Tv
+masked by =dev-vcs/cvs-1.12.12*: dev-vcs/cvs-1.12.12-r12
+.fi
+Unrelated, but to locate the mask given, use verbose mode on \fIq\fR's
+mask listing:
+.nf
+$ q -mv dev-vcs/cvs
+=dev-vcs/cvs-1.12.12* [/repo/gentoo/profiles/prefix/sunos/solaris/package.mask]
+.fi
 .SH "REPORTING BUGS"
 Please report bugs via http://bugs.gentoo.org/
 .br

diff --git a/qkeyword.c b/qkeyword.c
index 4a55b6a..4e84ebd 100644
--- a/qkeyword.c
+++ b/qkeyword.c
@@ -76,8 +76,9 @@ static set *archs = NULL;
 static char **archlist = NULL;
 static size_t archlist_count;
 static size_t arch_longest_len;
-const char status[3] = {'-', '~', '+'};
-int qkeyword_test_arch = 0;
+static const char status[3] = {'-', '~', '+'};
+static int qkeyword_test_arch = 0;
+static set *pmasks = NULL;
 
 enum { none = 0, testing, stable, minus };
 
@@ -226,13 +227,33 @@ qkeyword_imlate(tree_pkg_ctx *pkg_ctx, void *priv)
 }
 
 static int
-qkeyword_lstable(tree_pkg_ctx *pkg_ctx, void *priv)
+qkeyword_kw(tree_pkg_ctx *pkg_ctx, void *priv, int what)
 {
 	qkeyword_data *data = (qkeyword_data *)priv;
+	depend_atom *atom;
+	array_t *masks;
 
-	if (data->keywordsbuf[qkeyword_test_arch] == stable)
+	if (data->keywordsbuf[qkeyword_test_arch] == what)
 	{
-		printf("%s", atom_format(data->fmt, tree_get_atom(pkg_ctx, true)));
+		size_t n;
+		depend_atom *mask;
+
+		atom = tree_get_atom(pkg_ctx, false);
+		masks = get_set(atom_format("%[CAT]%[PN]", atom), pmasks);
+		if (masks != NULL) {
+			array_for_each(masks, n, mask) {
+				if (atom_compare(atom, mask) == EQUAL) {
+					if (verbose) {
+						printf("masked by %s: ", atom_to_string(mask));
+						printf("%s\n", atom_format(data->fmt,
+									tree_get_atom(pkg_ctx, true)));
+					}
+					return EXIT_FAILURE;
+				}
+			}
+		}
+
+		printf("%s\n", atom_format(data->fmt, tree_get_atom(pkg_ctx, true)));
 		return EXIT_SUCCESS;
 	}
 
@@ -240,17 +261,15 @@ qkeyword_lstable(tree_pkg_ctx *pkg_ctx, void *priv)
 }
 
 static int
-qkeyword_ltesting(tree_pkg_ctx *pkg_ctx, void *priv)
+qkeyword_lstable(tree_pkg_ctx *pkg_ctx, void *priv)
 {
-	qkeyword_data *data = (qkeyword_data *)priv;
-
-	if (data->keywordsbuf[qkeyword_test_arch] == testing)
-	{
-		printf("%s\n", atom_format(data->fmt, tree_get_atom(pkg_ctx, true)));
-		return EXIT_SUCCESS;
-	}
+	return qkeyword_kw(pkg_ctx, priv, stable);
+}
 
-	return EXIT_FAILURE;
+static int
+qkeyword_ltesting(tree_pkg_ctx *pkg_ctx, void *priv)
+{
+	return qkeyword_kw(pkg_ctx, priv, testing);
 }
 
 static int
@@ -868,6 +887,32 @@ int qkeyword_main(int argc, char **argv)
 	data.keywordsbuflen = 0;
 	data.qmaint = maint;
 
+	/* prepare masks for easy(er) matching by key-ing on CAT/PN */
+	{
+		DECLARE_ARRAY(masks);
+		array_t *bucket;
+		array_t *ebuck;
+		size_t n;
+		char *mask;
+		depend_atom *atom;
+
+		pmasks = create_set();
+
+		array_set(package_masks, masks);
+		array_for_each(masks, n, mask) {
+			if ((atom = atom_explode(mask)) == NULL)
+				continue;
+			bucket = xzalloc(sizeof(array_t));
+			xarraypush_ptr(bucket, atom);
+			ebuck = add_set_value(atom_format("%[CAT]%[PN]", atom),
+					bucket, pmasks);
+			if (ebuck != NULL) {
+				xarraypush_ptr(ebuck, atom);
+				xarrayfree_int(bucket);
+			}
+		}
+	}
+
 	switch (action) {
 		case 'i': i = qkeyword_traverse(qkeyword_imlate, &data);        break;
 		case 'd': i = qkeyword_traverse(qkeyword_dropped, &data);


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/
@ 2023-01-30 14:14 Fabian Groffen
  0 siblings, 0 replies; 9+ messages in thread
From: Fabian Groffen @ 2023-01-30 14:14 UTC (permalink / raw
  To: gentoo-commits

commit:     49da23ddba819dcf41bc3e5c1a2fb1c8801895d3
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Mon Jan 30 14:14:11 2023 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Mon Jan 30 14:14:11 2023 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=49da23dd

qdepends: add support for IDEPEND, #892533

Bug: https://bugs.gentoo.org/892533
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qdepends.desc |  3 ++-
 man/qdepends.1            |  8 ++++++--
 qdepends.c                | 38 +++++++++++++++++++++++++-------------
 3 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/man/include/qdepends.desc b/man/include/qdepends.desc
index 19000d0..70b27be 100644
--- a/man/include/qdepends.desc
+++ b/man/include/qdepends.desc
@@ -4,7 +4,8 @@ applet has two different modes, forward and reverse dependency querying.
 Default operation is forward mode, answering the queries "what does
 package X depend on", while reverse mode answers "what packages depend
 on X".  Both modes can be further specified into build (DEPEND), run
-(RDEPEND), post (PDEPEND) and EAPI7's BDEPEND dependencies.
+(RDEPEND), post (PDEPEND), EAPI7's build (BDEPEND) and EAPI8's
+install-time (IDEPEND) dependencies.
 .P
 By default, \fIqdepends\fR returns the unique set of atoms that match
 all dependency variables.  To split this out per variable, use \fB-v\fR

diff --git a/man/qdepends.1 b/man/qdepends.1
index 5e5b00a..95e2b37 100644
--- a/man/qdepends.1
+++ b/man/qdepends.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH qdepends "1" "May 2022" "Gentoo Foundation" "qdepends"
+.TH qdepends "1" "Jan 2023" "Gentoo Foundation" "qdepends"
 .SH NAME
 qdepends \- show dependency info
 .SH SYNOPSIS
@@ -12,7 +12,8 @@ applet has two different modes, forward and reverse dependency querying.
 Default operation is forward mode, answering the queries "what does
 package X depend on", while reverse mode answers "what packages depend
 on X".  Both modes can be further specified into build (DEPEND), run
-(RDEPEND), post (PDEPEND) and EAPI7's BDEPEND dependencies.
+(RDEPEND), post (PDEPEND), EAPI7's build (BDEPEND) and EAPI8's
+install-time (IDEPEND) dependencies.
 .P
 By default, \fIqdepends\fR returns the unique set of atoms that match
 all dependency variables.  To split this out per variable, use \fB-v\fR
@@ -52,6 +53,9 @@ Show PDEPEND info.
 \fB\-b\fR, \fB\-\-bdepend\fR
 Show BDEPEND info.
 .TP
+\fB\-I\fR, \fB\-\-idepend\fR
+Show IDEPEND info.
+.TP
 \fB\-Q\fR, \fB\-\-query\fR
 Query reverse deps.  This basically reverses the search to any
 package that references \fI<arg>\fR in DEPEND, RDEPEND, PDEPEND or BDEPEND.

diff --git a/qdepends.c b/qdepends.c
index f222011..1ecfab5 100644
--- a/qdepends.c
+++ b/qdepends.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2022 Gentoo Authors
+ * Copyright 2005-2023 Gentoo Authors
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
@@ -22,12 +22,13 @@
 #include "xasprintf.h"
 #include "xregex.h"
 
-#define QDEPENDS_FLAGS "drpbQitUF:SR" COMMON_FLAGS
+#define QDEPENDS_FLAGS "drpbIQitUF:SR" COMMON_FLAGS
 static struct option const qdepends_long_opts[] = {
 	{"depend",    no_argument, NULL, 'd'},
 	{"rdepend",   no_argument, NULL, 'r'},
 	{"pdepend",   no_argument, NULL, 'p'},
 	{"bdepend",   no_argument, NULL, 'b'},
+	{"idepend",   no_argument, NULL, 'I'},
 	{"query",     no_argument, NULL, 'Q'},
 	{"installed", no_argument, NULL, 'i'},
 	{"tree",      no_argument, NULL, 't'},
@@ -42,6 +43,7 @@ static const char * const qdepends_opts_help[] = {
 	"Show RDEPEND info",
 	"Show PDEPEND info",
 	"Show BDEPEND info",
+	"Show IDEPEND info",
 	"Query reverse deps",
 	"Search installed packages using VDB",
 	"Search available ebuilds in the tree",
@@ -71,17 +73,22 @@ struct qdepends_opt_state {
 #define QMODE_RDEPEND    (1<<1)
 #define QMODE_PDEPEND    (1<<2)
 #define QMODE_BDEPEND    (1<<3)
+#define QMODE_IDEPEND    (1<<4)
 #define QMODE_INSTALLED  (1<<5)
 #define QMODE_TREE       (1<<6)
 #define QMODE_REVERSE    (1<<7)
 #define QMODE_FILTERUSE  (1<<8)
 
+#define QMODE_DEP_FIRST  QMODE_DEPEND
+#define QMODE_DEP_LAST   QMODE_IDEPEND
+
 const char *depend_files[] = {  /* keep *DEPEND aligned with above defines */
 	/* 0 */ "DEPEND",
 	/* 1 */ "RDEPEND",
 	/* 2 */ "PDEPEND",
 	/* 3 */ "BDEPEND",
-	/* 4 */ NULL
+	/* 4 */ "IDEPEND",
+	/* 5 */ NULL
 };
 
 static bool
@@ -161,15 +168,19 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	xarrayfree_int(state->deps);
 	clear_set(state->udeps);
 
+#define get_depstr(X) \
+	i == QMODE_DEPEND  ? tree_pkg_meta_get(pkg_ctx, DEPEND)  : \
+	i == QMODE_RDEPEND ? tree_pkg_meta_get(pkg_ctx, RDEPEND) : \
+	i == QMODE_PDEPEND ? tree_pkg_meta_get(pkg_ctx, PDEPEND) : \
+	i == QMODE_BDEPEND ? tree_pkg_meta_get(pkg_ctx, BDEPEND) : \
+		                 tree_pkg_meta_get(pkg_ctx, IDEPEND) ;
+
 	dfile = depend_files;
-	for (i = QMODE_DEPEND; i <= QMODE_BDEPEND; i <<= 1, dfile++) {
+	for (i = QMODE_DEP_FIRST; i <= QMODE_DEP_LAST; i <<= 1, dfile++) {
 		if (!(state->qmode & i))
 			continue;
 
-		depstr = i == 1<<0 ? tree_pkg_meta_get(pkg_ctx, DEPEND) :
-				 i == 1<<1 ? tree_pkg_meta_get(pkg_ctx, RDEPEND) :
-				 i == 1<<2 ? tree_pkg_meta_get(pkg_ctx, PDEPEND) :
-				             tree_pkg_meta_get(pkg_ctx, BDEPEND);
+		depstr = get_depstr(i);
 		if (depstr == NULL)
 			continue;
 		dep_tree = dep_grow_tree(depstr);
@@ -193,10 +204,7 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 				tree_pkg_ctx *vpkg =
 					tree_open_pkg(vcat, pkg_ctx->name);
 				if (vpkg != NULL) {
-					depstr = i == 1<<0 ? tree_pkg_meta_get(vpkg, DEPEND) :
-							 i == 1<<1 ? tree_pkg_meta_get(vpkg, RDEPEND) :
-							 i == 1<<2 ? tree_pkg_meta_get(vpkg, PDEPEND) :
-							             tree_pkg_meta_get(vpkg, BDEPEND);
+					depstr = get_depstr(i);
 					if (depstr != NULL) {
 						dep_node *dep_vdb = dep_grow_tree(depstr);
 						if (dep_vdb != NULL) {
@@ -293,6 +301,8 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	if (verbose && ret == 1)
 		printf("\n");
 
+#undef get_depstr
+
 	if (!verbose) {
 		if ((state->qmode & QMODE_REVERSE) == 0 || ret == 1) {
 			for (n = list_set(state->udeps, &d); n > 0; n--)
@@ -335,6 +345,7 @@ int qdepends_main(int argc, char **argv)
 		case 'r': state.qmode |= QMODE_RDEPEND;   break;
 		case 'p': state.qmode |= QMODE_PDEPEND;   break;
 		case 'b': state.qmode |= QMODE_BDEPEND;   break;
+		case 'I': state.qmode |= QMODE_IDEPEND;   break;
 		case 'Q': state.qmode |= QMODE_REVERSE;   break;
 		case 'i': state.qmode |= QMODE_INSTALLED; break;
 		case 't': state.qmode |= QMODE_TREE;      break;
@@ -350,7 +361,8 @@ int qdepends_main(int argc, char **argv)
 		state.qmode |= QMODE_DEPEND  |
 					   QMODE_RDEPEND |
 					   QMODE_PDEPEND |
-					   QMODE_BDEPEND;
+					   QMODE_BDEPEND |
+					   QMODE_IDEPEND ;
 	}
 
 	/* default to installed packages */


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-01-30 14:15 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-09  9:53 [gentoo-commits] proj/portage-utils:master commit in: man/, /, man/include/ Fabian Groffen
  -- strict thread matches above, loose matches on Subject: below --
2023-01-30 14:14 Fabian Groffen
2019-12-27 19:16 Fabian Groffen
2019-07-18 18:36 Fabian Groffen
2019-05-17 14:35 Fabian Groffen
2019-05-13 13:39 Fabian Groffen
2019-04-28  7:58 Fabian Groffen
2019-03-29 16:35 Fabian Groffen
2019-03-07 18:20 Fabian Groffen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox