commit: 307939315330f631f9f526f8560a2ce09605fc9c
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Wed Feb 17 20:19:58 2021 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Wed Feb 17 20:19:58 2021 +0000
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=30793931
qwhich: add applet to show paths to packages
e.g. to find the ebuild dir of bash in thw tree:
% qwhich -dt bash
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
Makefile.am | 3 +
man/qwhich.1 | 79 +++++++++++++++++++++++++
qwhich.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 272 insertions(+)
diff --git a/Makefile.am b/Makefile.am
index ceded24..cf578f4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,6 +23,7 @@ APPLETS = \
qsize \
qtbz2 \
quse \
+ qwhich \
qxpak \
$(NULL)
@@ -42,6 +43,7 @@ dist_man_MANS = \
man/qsize.1 \
man/qtbz2.1 \
man/quse.1 \
+ man/qwhich.1 \
man/qxpak.1 \
$(NULL)
@@ -63,6 +65,7 @@ q_SOURCES = \
qsize.c \
qtbz2.c \
quse.c \
+ qwhich.c \
qxpak.c \
$(NULL)
q_CPPFLAGS = \
diff --git a/man/qwhich.1 b/man/qwhich.1
new file mode 100644
index 0000000..dce52c2
--- /dev/null
+++ b/man/qwhich.1
@@ -0,0 +1,79 @@
+.\" generated by mkman.py, please do NOT edit!
+.TH qwhich "1" "Feb 2021" "Gentoo Foundation" "qwhich"
+.SH NAME
+qwhich \- find path to pkg
+.SH SYNOPSIS
+.B qwhich
+\fI[opts] <useflag>\fR
+.SH DESCRIPTION
+
+.SH OPTIONS
+.TP
+\fB\-I\fR, \fB\-\-vdb\fR
+Look in VDB (installed packages).
+.TP
+\fB\-b\fR, \fB\-\-binpkg\fR
+Look at binary packages.
+.TP
+\fB\-t\fR, \fB\-\-tree\fR
+Look in main tree and overlays.
+.TP
+\fB\-p\fR, \fB\-\-pretty\fR
+Print (pretty) atom instead of path for use with -F.
+.TP
+\fB\-d\fR, \fB\-\-dir\fR
+Print directory instead of path.
+.TP
+\fB\-f\fR, \fB\-\-first\fR
+Stop searching after first match.
+.TP
+\fB\-F\fR \fI<arg>\fR, \fB\-\-format\fR \fI<arg>\fR
+Print matched using given format string.
+.TP
+\fB\-\-root\fR \fI<arg>\fR
+Set the ROOT env var.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Report full package versions, emit more elaborate output.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Tighter output; suppress warnings.
+.TP
+\fB\-C\fR, \fB\-\-nocolor\fR
+Don't output color.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print this help and exit.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print version and exit.
+
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.br
+Product: Portage Development; Component: Tools
+.SH AUTHORS
+.nf
+Ned Ludd <[email protected]>
+Mike Frysinger <[email protected]>
+Fabian Groffen <[email protected]>
+.fi
+.SH "SEE ALSO"
+.BR q (1),
+.BR qatom (1),
+.BR qcheck (1),
+.BR qdepends (1),
+.BR qfile (1),
+.BR qgrep (1),
+.BR qkeyword (1),
+.BR qlist (1),
+.BR qlop (1),
+.BR qmanifest (1),
+.BR qmerge (1),
+.BR qpkg (1),
+.BR qsearch (1),
+.BR qsize (1),
+.BR qtbz2 (1),
+.BR qtegrity (1),
+.BR quse (1),
+.BR qxpak (1)
diff --git a/qwhich.c b/qwhich.c
new file mode 100644
index 0000000..3a0c791
--- /dev/null
+++ b/qwhich.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2021 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ *
+ * Copyright 2021- Fabian Groffen - <[email protected]>
+ */
+
+#include "main.h"
+#include "applets.h"
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+#include <sys/stat.h>
+
+#include "atom.h"
+#include "tree.h"
+
+#define QWHICH_FLAGS "IbtpdfF:" COMMON_FLAGS
+static struct option const qwhich_long_opts[] = {
+ {"vdb", no_argument, NULL, 'I'},
+ {"binpkg", no_argument, NULL, 'b'},
+ {"tree", no_argument, NULL, 't'},
+ {"pretty", no_argument, NULL, 'p'},
+ {"dir", no_argument, NULL, 'd'},
+ {"first", no_argument, NULL, 'f'},
+ {"format", a_argument, NULL, 'F'},
+ COMMON_LONG_OPTS
+};
+static const char * const qwhich_opts_help[] = {
+ "Look in VDB (installed packages)",
+ "Look at binary packages",
+ "Look in main tree and overlays",
+ "Print (pretty) atom instead of path for use with -F",
+ "Print directory instead of path",
+ "Stop searching after first match",
+ "Print matched using given format string",
+ COMMON_OPTS_HELP
+};
+static const char qwhich_desc[] = "";
+#define qwhich_usage(ret) \
+ usage(ret, QWHICH_FLAGS, qwhich_long_opts, qwhich_opts_help,
qwhich_desc, lookup_applet_idx("qwhich"))
+
+struct qwhich_mode {
+ char do_vdb:1;
+ char do_binpkg:1;
+ char do_tree:1;
+ char print_atom:1;
+ char print_path:1;
+ char match_first:1;
+ const char *fmt;
+};
+
+int qwhich_main(int argc, char **argv)
+{
+ depend_atom *atom;
+ DECLARE_ARRAY(atoms);
+ DECLARE_ARRAY(trees);
+ struct qwhich_mode m;
+ struct tree_match_ctx *tmc;
+ struct tree_match_ctx *tmcw;
+ size_t i;
+ size_t j;
+ char *overlay;
+ size_t n;
+ int ret;
+ tree_ctx *t;
+ int repolen;
+
+ memset(&m, 0, sizeof(m));
+
+ while ((ret = GETOPT_LONG(QWHICH, qwhich, "")) != -1) {
+ switch (ret) {
+ COMMON_GETOPTS_CASES(qwhich)
+
+ case 'I': m.do_vdb = true; break;
+ case 'b': m.do_binpkg = true; break;
+ case 't': m.do_tree = true; break;
+ case 'p': m.print_atom = true; break;
+ case 'd': m.print_path = true; break;
+ case 'f': m.match_first = true; break;
+ case 'F': m.fmt = optarg; break;
+ }
+ }
+
+ /* defaults: no options at all, enable first match,
+ * no selectors, enable tree + overlays */
+ if (!m.do_vdb && !m.do_binpkg && !m.do_tree) {
+ if (!m.print_atom && !m.print_path && !m.match_first && m.fmt
== NULL)
+ m.match_first = true;
+ m.do_tree = true;
+ }
+
+ /* when printing path, we better just match the first, else we get a
+ * lot of dups */
+ if (m.print_path)
+ m.match_first = true;
+
+ /* set format if none given */
+ if (m.fmt == NULL) {
+ if (verbose)
+ m.fmt = "%[CATEGORY]%[PF]";
+ else
+ m.fmt = "%[CATEGORY]%[PN]";
+ } else {
+ /* makes no sense to use formatter if we're not going to use it
*/
+ m.print_atom = true;
+ }
+
+ argc -= optind;
+ argv += optind;
+ for (i = 0; i < (size_t)argc; ++i) {
+ atom = atom_explode(argv[i]);
+ if (!atom)
+ warn("invalid atom: %s", argv[i]);
+ else
+ xarraypush_ptr(atoms, atom);
+ }
+
+ /* TODO: silence when the path doesn't exist -- reasonable though? */
+ if (m.do_vdb) {
+ t = tree_open_vdb(portroot, portvdb);
+ if (t != NULL)
+ xarraypush_ptr(trees, t);
+ }
+ if (m.do_binpkg) {
+ t = tree_open_binpkg(portroot, pkgdir);
+ if (t != NULL)
+ xarraypush_ptr(trees, t);
+ }
+
+ if (m.do_tree) {
+ array_for_each(overlays, n, overlay) {
+ t = tree_open(portroot, overlay);
+ if (t != NULL)
+ xarraypush_ptr(trees, t);
+ }
+ }
+
+ /* at least keep the IO constrained to a tree at a time */
+ array_for_each(trees, j, t) {
+ if (t->cachetype == CACHE_METADATA_MD5)
+ repolen = strlen(t->path) -
(sizeof("/metadata/md5-cache") - 1);
+ else if (t->cachetype == CACHE_METADATA_PMS)
+ repolen = strlen(t->path) - (sizeof("/metadata/cache")
- 1);
+ else
+ repolen = 0;
+
+ array_for_each(atoms, i, atom) {
+ tmc = tree_match_atom(t, atom,
+ m.match_first ? TREE_MATCH_FIRST :
TREE_MATCH_DEFAULT);
+ for (tmcw = tmc; tmcw != NULL; tmcw = tmcw->next) {
+ if (m.print_atom) {
+ printf("%s\n", atom_format(m.fmt,
tmcw->atom));
+ } else {
+ if (t->cachetype == CACHE_METADATA_MD5
||
+ t->cachetype ==
CACHE_METADATA_PMS)
+ {
+ if (m.print_path)
+
printf("%s%.*s/%s%s/%s%s%s\n",
+ GREEN,
repolen, t->path,
+ BOLD,
tmcw->atom->CATEGORY,
+ DKBLUE,
tmcw->atom->PN,
+ NORM);
+ else
+
printf("%s%.*s/%s%s/%s%s/%s%s%s.ebuild%s\n",
+
DKGREEN, repolen, t->path,
+ BOLD,
tmcw->atom->CATEGORY,
+ DKBLUE,
tmcw->atom->PN,
+ BLUE,
tmcw->atom->P,
+
DKGREEN, NORM);
+ } else {
+ printf("%s%s%s\n", DKBLUE,
tmcw->path, NORM);
+ }
+ }
+ }
+ tree_match_close(tmc);
+ }
+ tree_close(t);
+ }
+ array_for_each(atoms, i, atom)
+ atom_implode(atom);
+ xarrayfree_int(atoms);
+ xarrayfree_int(trees);
+
+ return EXIT_SUCCESS;
+}