From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage-utils:master commit in: man/include/, /, man/
Date: Fri, 27 Dec 2019 16:57:06 +0000 (UTC) [thread overview]
Message-ID: <1577465758.032bd7e9200d1071b79f3a5d33906020fc805048.grobian@gentoo> (raw)
commit: 032bd7e9200d1071b79f3a5d33906020fc805048
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri Dec 27 16:55:58 2019 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri Dec 27 16:55:58 2019 +0000
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=032bd7e9
main: add masks support
Expose masks via q -m, store masks in preparation for applying masks
when listing available ebuilds.
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
main.c | 221 +++++++++++++++++++++++++++++++++--------------------
main.h | 2 +
man/include/q.desc | 2 +
man/q.1 | 13 +++-
q.c | 56 +++++++++++++-
5 files changed, 209 insertions(+), 85 deletions(-)
diff --git a/main.c b/main.c
index 869bf31..b5404cb 100644
--- a/main.c
+++ b/main.c
@@ -22,6 +22,7 @@
#include "eat_file.h"
#include "rmspace.h"
#include "scandirat.h"
+#include "set.h"
#include "xasprintf.h"
/* variables to control runtime behavior */
@@ -354,10 +355,12 @@ set_portage_env_var(env_vars *var, const char *value, const char *src)
}
}
-/* Helper to read a portage env file (e.g. make.conf), or recursively if
- * it points to a directory */
+/* Helper to read a portage file (e.g. make.conf, package.mask), or
+ * recursively if it points to a directory (we don't care about EAPI for
+ * dirs, basically PMS 5.2.5 EAPI restriction is ignored) */
+enum portage_file_type { ENV_FILE, PMASK_FILE };
static void
-read_portage_env_file(const char *file, env_vars vars[])
+read_portage_file(const char *file, enum portage_file_type type, void *data)
{
FILE *fp;
struct dirent **dents;
@@ -368,6 +371,8 @@ read_portage_env_file(const char *file, env_vars vars[])
size_t buflen = 0;
size_t line;
int i;
+ env_vars *vars = data;
+ set *masks = data;
if (getenv("DEBUG"))
fprintf(stderr, "profile %s\n", file);
@@ -384,7 +389,7 @@ read_portage_env_file(const char *file, env_vars vars[])
d->d_name[strlen(d->d_name) - 1] == '~')
continue;
snprintf(npath, sizeof(npath), "%s/%s", file, d->d_name);
- read_portage_env_file(npath, vars);
+ read_portage_file(npath, type, data);
}
scandir_free(dents, dentslen);
goto done;
@@ -402,84 +407,107 @@ read_portage_env_file(const char *file, env_vars vars[])
continue;
/* Handle "source" keyword */
- if (strncmp(buf, "source ", 7) == 0) {
- const char *sfile = buf + 7;
- char npath[_Q_PATH_MAX * 2];
+ if (type == ENV_FILE) {
+ if (strncmp(buf, "source ", 7) == 0) {
+ const char *sfile = buf + 7;
+ char npath[_Q_PATH_MAX * 2];
- if (sfile[0] != '/') {
- /* handle relative paths */
- size_t file_path_len;
+ if (sfile[0] != '/') {
+ /* handle relative paths */
+ size_t file_path_len;
- s = strrchr(file, '/');
- file_path_len = s - file + 1;
+ s = strrchr(file, '/');
+ file_path_len = s - file + 1;
- snprintf(npath, sizeof(npath), "%.*s/%s",
- (int)file_path_len, file, sfile);
- sfile = npath;
- }
-
- read_portage_env_file(sfile, vars);
- continue;
- }
+ snprintf(npath, sizeof(npath), "%.*s/%s",
+ (int)file_path_len, file, sfile);
+ sfile = npath;
+ }
- /* look for our desired variables and grab their value */
- for (i = 0; vars[i].name; ++i) {
- if (buf[vars[i].name_len] != '=' && buf[vars[i].name_len] != ' ')
- continue;
- if (strncmp(buf, vars[i].name, vars[i].name_len))
+ read_portage_file(sfile, type, data);
continue;
+ }
- /* make sure we handle spaces between the varname, the =,
- * and the value:
- * VAR=val VAR = val VAR="val"
- */
- s = buf + vars[i].name_len;
- if ((p = strchr(s, '=')) != NULL)
- s = p + 1;
- while (isspace(*s))
- ++s;
- if (*s == '"' || *s == '\'') {
- char *endq;
- char q = *s;
-
- /* make sure we handle spacing/comments after the quote */
- endq = strchr(s + 1, q);
- if (!endq) {
- /* If the last char is not a quote, then we span lines */
- size_t abuflen;
- char *abuf;
-
- abuf = NULL;
- while (getline(&abuf, &abuflen, fp) != -1) {
- buf = xrealloc(buf, buflen + abuflen);
- endq = strchr(abuf, q);
- if (endq)
- *endq = '\0';
-
- strcat(buf, abuf);
- buflen += abuflen;
-
- if (endq)
- break;
- }
- free(abuf);
-
- if (!endq)
- warn("%s:%zu: %s: quote mismatch",
- file, line, vars[i].name);
+ /* look for our desired variables and grab their value */
+ for (i = 0; vars[i].name; i++) {
+ if (buf[vars[i].name_len] != '=' &&
+ buf[vars[i].name_len] != ' ')
+ continue;
+ if (strncmp(buf, vars[i].name, vars[i].name_len))
+ continue;
- s = buf + vars[i].name_len + 2;
+ /* make sure we handle spaces between the varname, the =,
+ * and the value:
+ * VAR=val VAR = val VAR="val"
+ */
+ s = buf + vars[i].name_len;
+ if ((p = strchr(s, '=')) != NULL)
+ s = p + 1;
+ while (isspace(*s))
+ s++;
+ if (*s == '"' || *s == '\'') {
+ char *endq;
+ char q = *s;
+
+ /* make sure we handle spacing/comments after the quote */
+ endq = strchr(s + 1, q);
+ if (!endq) {
+ /* if the last char is not a quote,
+ * then we span lines */
+ size_t abuflen;
+ char *abuf;
+
+ abuf = NULL;
+ while (getline(&abuf, &abuflen, fp) != -1) {
+ buf = xrealloc(buf, buflen + abuflen);
+ endq = strchr(abuf, q);
+ if (endq)
+ *endq = '\0';
+
+ strcat(buf, abuf);
+ buflen += abuflen;
+
+ if (endq)
+ break;
+ }
+ free(abuf);
+
+ if (!endq)
+ warn("%s:%zu: %s: quote mismatch",
+ file, line, vars[i].name);
+
+ s = buf + vars[i].name_len + 2;
+ } else {
+ *endq = '\0';
+ s++;
+ }
} else {
- *endq = '\0';
- ++s;
+ /* no quotes, so chop the spacing/comments ourselves */
+ size_t off = strcspn(s, "# \t\n");
+ s[off] = '\0';
}
+
+ set_portage_env_var(&vars[i], s, file);
+ }
+ } else if (type == PMASK_FILE) {
+ /* trim leading space */
+ for (s = buf; isspace((int)*s); s++)
+ ;
+ if (*s == '\0')
+ continue;
+ if (*s == '-') {
+ /* negation/removal, lookup and drop mask if it exists;
+ * note that this only supports exact matches (PMS
+ * 5.2.5) so we don't even have to parse and use
+ * atom-compare here */
+ s++;
+ if ((p = del_set(s, masks, NULL)) != NULL)
+ free(p);
} else {
- /* no quotes, so chop the spacing/comments ourselves */
- size_t off = strcspn(s, "# \t\n");
- s[off] = '\0';
+ p = xstrdup(file);
+ if (add_set_value(s, p, masks) != NULL)
+ free(p);
}
-
- set_portage_env_var(&vars[i], s, file);
}
}
@@ -490,9 +518,10 @@ read_portage_env_file(const char *file, env_vars vars[])
/* Helper to recursively read stacked make.defaults in profiles */
static void
-read_portage_profile(const char *profile, env_vars vars[])
+read_portage_profile(const char *profile, env_vars vars[], set *masks)
{
char profile_file[_Q_PATH_MAX * 3];
+ char rpath[_Q_PATH_MAX];
size_t profile_len;
char *s;
char *p;
@@ -548,7 +577,9 @@ read_portage_profile(const char *profile, env_vars vars[])
snprintf(profile_file + profile_len,
sizeof(profile_file) - profile_len, "%s", s);
}
- read_portage_profile(profile_file, vars);
+ read_portage_profile(
+ realpath(profile_file, rpath) == NULL ? profile_file : rpath,
+ vars, masks);
/* restore original path in case we were repointed by profile */
if (p != NULL)
snprintf(profile_file, sizeof(profile_file), "%s/", profile);
@@ -557,9 +588,11 @@ read_portage_profile(const char *profile, env_vars vars[])
free(buf);
- /* now consume *this* profile's make.defaults */
+ /* now consume *this* profile's make.defaults and package.mask */
strcpy(profile_file + profile_len, "make.defaults");
- read_portage_env_file(profile_file, vars);
+ read_portage_file(profile_file, ENV_FILE, vars);
+ strcpy(profile_file + profile_len, "package.mask");
+ read_portage_file(profile_file, PMASK_FILE, masks);
}
static bool nocolor = 0;
@@ -598,6 +631,7 @@ env_vars vars_to_read[] = {
#undef _Q_EV
};
+set *package_masks = NULL;
/* Handle a single file in the repos.conf format. */
static void
@@ -716,10 +750,11 @@ initialize_portage_env(void)
const char *s;
env_vars *var;
char pathbuf[_Q_PATH_MAX];
+ char rpathbuf[_Q_PATH_MAX];
const char *configroot = getenv("PORTAGE_CONFIGROOT");
char *primary_overlay = NULL;
- /* initialize all the strings with their default value */
+ /* initialize all the properties with their default value */
for (i = 0; vars_to_read[i].name; ++i) {
var = &vars_to_read[i];
if (var->type != _Q_BOOL)
@@ -727,6 +762,8 @@ initialize_portage_env(void)
var->src = xstrdup(STR_DEFAULT);
}
+ package_masks = create_set();
+
/* figure out where to find our config files */
if (!configroot)
configroot = CONFIG_EPREFIX;
@@ -737,7 +774,7 @@ initialize_portage_env(void)
i--;
/* read overlays first so we can resolve repo references in profile
- * parent files */
+ * parent files (non PMS feature?) */
snprintf(pathbuf, sizeof(pathbuf), "%.*s", (int)i, configroot);
read_repos_conf(pathbuf, "/usr/share/portage/config/repos.conf",
&primary_overlay);
@@ -747,23 +784,41 @@ initialize_portage_env(void)
snprintf(pathbuf, sizeof(pathbuf),
"%.*s/usr/share/portage/config/make.globals",
(int)i, configroot);
- read_portage_env_file(pathbuf, vars_to_read);
+ read_portage_file(pathbuf, ENV_FILE, vars_to_read);
+
+ /* start with base masks, Portage behaviour PMS 5.2.8 */
+ if (primary_overlay != NULL) {
+ char *overlay;
+ size_t n;
+ array_for_each(overlay_names, n, overlay) {
+ if (overlay == primary_overlay) {
+ snprintf(pathbuf, sizeof(pathbuf), "%s/profiles/package.mask",
+ (char *)array_get_elem(overlays, n));
+ read_portage_file(pathbuf, PMASK_FILE, package_masks);
+ break;
+ }
+ }
+ }
/* walk all the stacked profiles */
snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/make.profile",
(int)i, configroot);
- read_portage_profile(pathbuf, vars_to_read);
+ read_portage_profile(
+ realpath(pathbuf, rpathbuf) == NULL ? pathbuf : rpathbuf,
+ vars_to_read, package_masks);
snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/portage/make.profile",
(int)i, configroot);
- read_portage_profile(pathbuf, vars_to_read);
+ read_portage_profile(
+ realpath(pathbuf, rpathbuf) == NULL ? pathbuf : rpathbuf,
+ vars_to_read, package_masks);
- /* now read all the config files */
+ /* now read all Portage's config files */
snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/make.conf",
(int)i, configroot);
- read_portage_env_file(pathbuf, vars_to_read);
+ read_portage_file(pathbuf, ENV_FILE, vars_to_read);
snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/portage/make.conf",
(int)i, configroot);
- read_portage_env_file(pathbuf, vars_to_read);
+ read_portage_file(pathbuf, ENV_FILE, vars_to_read);
/* finally, check the env */
for (i = 0; vars_to_read[i].name; i++) {
diff --git a/main.h b/main.h
index 98e5cbb..68b9795 100644
--- a/main.h
+++ b/main.h
@@ -24,6 +24,7 @@
#include "colors.h"
#include "i18n.h"
+#include "set.h"
extern const char *argv0;
@@ -152,5 +153,6 @@ typedef struct {
char *src;
} env_vars;
extern env_vars vars_to_read[];
+extern set *package_masks;
#endif
diff --git a/man/include/q.desc b/man/include/q.desc
index 7109c46..7d38ba2 100644
--- a/man/include/q.desc
+++ b/man/include/q.desc
@@ -6,3 +6,5 @@ After version 0.74 of portage-utils, the cache functionality was removed
in favour of using various trees directly, and optionally the caches
therein. As such the \fB-r\fR and \fB-m\fR options were removed. It is
no longer necessary to initialise the cache at any time.
+.P
+After version 0.82, the \fB-m\fR flag got repurposed for listing masks.
diff --git a/man/q.1 b/man/q.1
index 886b00f..21a09b3 100644
--- a/man/q.1
+++ b/man/q.1
@@ -1,5 +1,5 @@
.\" generated by mkman.py, please do NOT edit!
-.TH q "1" "Nov 2019" "Gentoo Foundation" "q"
+.TH q "1" "Dec 2019" "Gentoo Foundation" "q"
.SH NAME
q \- invoke a portage utility applet
.SH SYNOPSIS
@@ -14,6 +14,8 @@ After version 0.74 of portage-utils, the cache functionality was removed
in favour of using various trees directly, and optionally the caches
therein. As such the \fB-r\fR and \fB-m\fR options were removed. It is
no longer necessary to initialise the cache at any time.
+.P
+After version 0.82, the \fB-m\fR flag got repurposed for listing masks.
.SH OPTIONS
.TP
\fB\-i\fR, \fB\-\-install\fR
@@ -26,6 +28,15 @@ see the source (file) where the overlay was declared.
\fB\-e\fR, \fB\-\-envvar\fR
Print used environment variables and found values. Use \fI-v\fR to
see the source (file, environment) where the variable was declared.
+Additional arguments are treated as variable names to print the
+values for. If just one name is given, only the value is printed if
+matched. When no arguments or more than one argument is given, the
+variable name and the value is printed as a shell-style declaration.
+.TP
+\fB\-m\fR, \fB\-\-masks\fR
+Print the masks from package.mask files found. Use \fI-v\fR to see
+the source (file) where the mask was declared. Additional arguments
+are treated as atom selectors which must match the masks.
.TP
\fB\-\-root\fR \fI<arg>\fR
Set the ROOT env var.
diff --git a/q.c b/q.c
index f137b04..4a2fd62 100644
--- a/q.c
+++ b/q.c
@@ -19,21 +19,24 @@
#include <libproc.h>
#endif
+#include "atom.h"
#include "basename.h"
#include "eat_file.h"
#include "rmspace.h"
-#define Q_FLAGS "ioe" COMMON_FLAGS
+#define Q_FLAGS "ioem" COMMON_FLAGS
static struct option const q_long_opts[] = {
{"install", no_argument, NULL, 'i'},
{"overlays", no_argument, NULL, 'o'},
{"envvar", no_argument, NULL, 'e'},
+ {"masks", no_argument, NULL, 'm'},
COMMON_LONG_OPTS
};
static const char * const q_opts_help[] = {
"Install symlinks for applets",
"Print available overlays (read from repos.conf)",
"Print used variables and their found values",
+ "Print (package.)masks for the current profile",
COMMON_OPTS_HELP
};
#define q_usage(ret) usage(ret, Q_FLAGS, q_long_opts, q_opts_help, NULL, lookup_applet_idx("q"))
@@ -81,6 +84,7 @@ int q_main(int argc, char **argv)
bool install;
bool print_overlays;
bool print_vars;
+ bool print_masks;
const char *p;
APPLET func;
@@ -100,12 +104,14 @@ int q_main(int argc, char **argv)
install = false;
print_overlays = false;
print_vars = false;
+ print_masks = false;
while ((i = GETOPT_LONG(Q, q, "+")) != -1) {
switch (i) {
COMMON_GETOPTS_CASES(q)
case 'i': install = true; break;
case 'o': print_overlays = true; break;
case 'e': print_vars = true; break;
+ case 'm': print_masks = true; break;
}
}
@@ -258,6 +264,54 @@ int q_main(int argc, char **argv)
return 0;
}
+ if (print_masks) {
+ DECLARE_ARRAY(masks);
+ DECLARE_ARRAY(files);
+ char *mask;
+ size_t n;
+ int j;
+ bool match;
+ depend_atom *atom;
+ depend_atom *qatom;
+
+ array_set(package_masks, masks);
+ values_set(package_masks, files);
+
+ array_for_each(masks, n, mask) {
+ if ((atom = atom_explode(mask)) == NULL)
+ continue;
+
+ match = true;
+ if (argc > optind) {
+ match = false;
+ for (j = optind; j < argc; j++) {
+ qatom = atom_explode(argv[j]);
+ if (qatom != NULL && atom_compare(atom, qatom) == EQUAL)
+ match = true;
+ atom_implode(qatom);
+ if (match)
+ break;
+ }
+ }
+ if (!match)
+ continue;
+
+ printf("%s", atom_format(
+ "%[pfx]%[CAT]%[PF]%[SLOT]%[SUBSLOT]%[sfx]%[USE]%[REPO]",
+ atom));
+ if (verbose)
+ printf(" [%s]\n", (char *)array_get_elem(files, n));
+ else
+ printf("\n");
+ atom_implode(atom);
+ }
+
+ xarrayfree_int(masks);
+ xarrayfree_int(files);
+
+ return 0;
+ }
+
if (argc == optind)
q_usage(EXIT_FAILURE);
if ((func = lookup_applet(argv[optind])) == NULL)
next reply other threads:[~2019-12-27 16:57 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-27 16:57 Fabian Groffen [this message]
-- strict thread matches above, loose matches on Subject: below --
2021-02-20 12:23 [gentoo-commits] proj/portage-utils:master commit in: man/include/, /, man/ Fabian Groffen
2019-06-19 7:31 Fabian Groffen
2019-04-12 18:50 Fabian Groffen
2018-04-12 19:33 Fabian Groffen
2018-04-03 15:21 Fabian Groffen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1577465758.032bd7e9200d1071b79f3a5d33906020fc805048.grobian@gentoo \
--to=grobian@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox