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;
+}

Reply via email to