[PATCH 0/4] add pacman-conf utility

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/4] add pacman-conf utility

Andrew Gregory
Parsing pacman.conf is so hard that even our own scripts don't do it
correctly.  pacman-conf is a dedicated utility scripts can use to
correctly parse values from pacman.conf.  This is a conversion of an
earlier version of pacconf from pacutils that has been relicensed and
renamed to avoid a file conflict.  I make no promises that I've
correctly adjusted the automake configuration for this type of build,
but it works for me.

Andrew Gregory (4):
  extract raw config file parser
  extract default settings to separate function
  add pacman-conf utility
  use pacman-conf in scripts

 scripts/completion/zsh_completion.in |   4 +-
 scripts/pacman-db-upgrade.sh.in      |  21 +-
 scripts/pacman-key.sh.in             |   2 +-
 src/pacman/conf.c                    | 179 +++++++-------
 src/pacman/conf.h                    |   2 +
 src/util/.gitignore                  |   2 +
 src/util/Makefile.am                 |  21 +-
 src/util/pacman-conf.c               | 437 +++++++++++++++++++++++++++++++++++
 8 files changed, 562 insertions(+), 106 deletions(-)
 create mode 100644 src/util/pacman-conf.c

--
2.15.1
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/4] extract raw config file parser

Andrew Gregory
To allow pacman-conf to parse the configuration file without having to
also setup alpm.

Signed-off-by: Andrew Gregory <[hidden email]>
---
 src/pacman/conf.c | 13 +++++++++----
 src/pacman/conf.h |  1 +
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index a283d7f4..e4980ed2 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -1036,6 +1036,14 @@ static int _parse_directive(const char *file, int linenum, const char *name,
  }
 }
 
+int parseconfigfile(const char *file)
+{
+ struct section_t section;
+ memset(&section, 0, sizeof(struct section_t));
+ pm_printf(ALPM_LOG_DEBUG, "config: attempting to read file %s\n", file);
+ return parse_ini(file, _parse_directive, &section);
+}
+
 /** Parse a configuration file.
  * @param file path to the config file
  * @return 0 on success, non-zero on error
@@ -1043,10 +1051,7 @@ static int _parse_directive(const char *file, int linenum, const char *name,
 int parseconfig(const char *file)
 {
  int ret;
- struct section_t section;
- memset(&section, 0, sizeof(struct section_t));
- pm_printf(ALPM_LOG_DEBUG, "config: attempting to read file %s\n", file);
- if((ret = parse_ini(file, _parse_directive, &section))) {
+ if((ret = parseconfigfile(file))) {
  return ret;
  }
  pm_printf(ALPM_LOG_DEBUG, "config: finished parsing %s\n", file);
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 53b44be6..e937051b 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -242,6 +242,7 @@ void config_repo_free(config_repo_t *repo);
 
 int config_set_arch(const char *arch);
 int parseconfig(const char *file);
+int parseconfigfile(const char *file);
 #endif /* PM_CONF_H */
 
 /* vim: set noet: */
--
2.15.1
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/4] extract default settings to separate function

Andrew Gregory
In reply to this post by Andrew Gregory
Default values for configuration settings were being set during alpm
setup and in some cases were never saved back to the original config
struct.  Refactoring all default settings into a separate function and
saving them onto the original config struct will allow pacman-conf to
resolve the defaults without having to setup alpm.

Signed-off-by: Andrew Gregory <[hidden email]>
---
 src/pacman/conf.c | 166 +++++++++++++++++++++++++++++-------------------------
 src/pacman/conf.h |   1 +
 2 files changed, 89 insertions(+), 78 deletions(-)

diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index e4980ed2..1ad75405 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -616,37 +616,39 @@ static int _parse_options(const char *key, char *value,
  return 0;
 }
 
-static int _add_mirror(alpm_db_t *db, char *value)
+static char *replace_server_vars(config_t *c, config_repo_t *r, const char *s)
 {
- const char *dbname = alpm_db_get_name(db);
- /* let's attempt a replacement for the current repo */
- char *temp = strreplace(value, "$repo", dbname);
- /* let's attempt a replacement for the arch */
- const char *arch = config->arch;
- char *server;
- if(arch) {
- server = strreplace(temp, "$arch", arch);
+ if(c->arch == NULL && strstr(s, "$arch")) {
+ pm_printf(ALPM_LOG_ERROR,
+ _("mirror '%s' contains the '%s' variable, but no '%s' is defined.\n"),
+ s, "$arch", "Architecture");
+ return NULL;
+ }
+
+ if(c->arch) {
+ char *temp, *replaced;
+
+ replaced = strreplace(s, "$arch", c->arch);
+
+ temp = replaced;
+ replaced = strreplace(temp, "$repo", r->name);
  free(temp);
+
+ return replaced;
  } else {
- if(strstr(temp, "$arch")) {
- free(temp);
- pm_printf(ALPM_LOG_ERROR,
- _("mirror '%s' contains the '%s' variable, but no '%s' is defined.\n"),
- value, "$arch", "Architecture");
- return 1;
- }
- server = temp;
+ return strreplace(s, "$repo", r->name);
  }
+}
 
- if(alpm_db_add_server(db, server) != 0) {
+static int _add_mirror(alpm_db_t *db, char *value)
+{
+ if(alpm_db_add_server(db, value) != 0) {
  /* pm_errno is set by alpm_db_setserver */
  pm_printf(ALPM_LOG_ERROR, _("could not add server URL to database '%s': %s (%s)\n"),
- dbname, server, alpm_strerror(alpm_errno(config->handle)));
- free(server);
+ alpm_db_get_name(db), value, alpm_strerror(alpm_errno(config->handle)));
  return 1;
  }
 
- free(server);
  return 0;
 }
 
@@ -655,9 +657,6 @@ static int register_repo(config_repo_t *repo)
  alpm_list_t *i;
  alpm_db_t *db;
 
- repo->siglevel = merge_siglevel(config->siglevel,
- repo->siglevel, repo->siglevel_mask);
-
  db = alpm_register_syncdb(config->handle, repo->name, repo->siglevel);
  if(db == NULL) {
  pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)\n"),
@@ -665,18 +664,12 @@ static int register_repo(config_repo_t *repo)
  return 1;
  }
 
- pm_printf(ALPM_LOG_DEBUG,
- "setting usage of %d for %s repository\n",
- repo->usage == 0 ? ALPM_DB_USAGE_ALL : repo->usage,
- repo->name);
- alpm_db_set_usage(db, repo->usage == 0 ? ALPM_DB_USAGE_ALL : repo->usage);
+ pm_printf(ALPM_LOG_DEBUG, "setting usage of %d for %s repository\n",
+ repo->usage, repo->name);
+ alpm_db_set_usage(db, repo->usage);
 
  for(i = repo->servers; i; i = alpm_list_next(i)) {
- char *value = i->data;
- if(_add_mirror(db, value) != 0) {
- pm_printf(ALPM_LOG_ERROR,
- _("could not add mirror '%s' to database '%s' (%s)\n"),
- value, repo->name, alpm_strerror(alpm_errno(config->handle)));
+ if(_add_mirror(db, i->data) != 0) {
  return 1;
  }
  }
@@ -699,25 +692,6 @@ static int setup_libalpm(void)
 
  pm_printf(ALPM_LOG_DEBUG, "setup_libalpm called\n");
 
- /* Configure root path first. If it is set and dbpath/logfile were not
- * set, then set those as well to reside under the root. */
- if(config->rootdir) {
- char path[PATH_MAX];
- if(!config->dbpath) {
- snprintf(path, PATH_MAX, "%s/%s", config->rootdir, DBPATH + 1);
- config->dbpath = strdup(path);
- }
- if(!config->logfile) {
- snprintf(path, PATH_MAX, "%s/%s", config->rootdir, LOGFILE + 1);
- config->logfile = strdup(path);
- }
- } else {
- config->rootdir = strdup(ROOTDIR);
- if(!config->dbpath) {
- config->dbpath = strdup(DBPATH);
- }
- }
-
  /* initialize library */
  handle = alpm_initialize(config->rootdir, config->dbpath, &err);
  if(!handle) {
@@ -740,7 +714,6 @@ static int setup_libalpm(void)
  alpm_option_set_dbext(handle, ".files");
  }
 
- config->logfile = config->logfile ? config->logfile : strdup(LOGFILE);
  ret = alpm_option_set_logfile(handle, config->logfile);
  if(ret != 0) {
  pm_printf(ALPM_LOG_ERROR, _("problem setting logfile '%s' (%s)\n"),
@@ -750,7 +723,6 @@ static int setup_libalpm(void)
 
  /* Set GnuPG's home directory. This is not relative to rootdir, even if
  * rootdir is defined. Reasoning: gpgdir contains configuration data. */
- config->gpgdir = config->gpgdir ? config->gpgdir : strdup(GPGDIR);
  ret = alpm_option_set_gpgdir(handle, config->gpgdir);
  if(ret != 0) {
  pm_printf(ALPM_LOG_ERROR, _("problem setting gpgdir '%s' (%s)\n"),
@@ -760,39 +732,21 @@ static int setup_libalpm(void)
 
  /* Set user hook directory. This is not relative to rootdir, even if
  * rootdir is defined. Reasoning: hookdir contains configuration data. */
- if(config->hookdirs == NULL) {
- if((ret = alpm_option_add_hookdir(handle, HOOKDIR)) != 0) {
+ /* add hook directories 1-by-1 to avoid overwriting the system directory */
+ for(i = config->hookdirs; i; i = alpm_list_next(i)) {
+ if((ret = alpm_option_add_hookdir(handle, i->data)) != 0) {
  pm_printf(ALPM_LOG_ERROR, _("problem adding hookdir '%s' (%s)\n"),
- HOOKDIR, alpm_strerror(alpm_errno(handle)));
+ (char *) i->data, alpm_strerror(alpm_errno(handle)));
  return ret;
  }
- } else {
- /* add hook directories 1-by-1 to avoid overwriting the system directory */
- for(i = config->hookdirs; i; i = alpm_list_next(i)) {
- if((ret = alpm_option_add_hookdir(handle, i->data)) != 0) {
- pm_printf(ALPM_LOG_ERROR, _("problem adding hookdir '%s' (%s)\n"),
- (char *) i->data, alpm_strerror(alpm_errno(handle)));
- return ret;
- }
- }
  }
 
- /* add a default cachedir if one wasn't specified */
- if(config->cachedirs == NULL) {
- alpm_option_add_cachedir(handle, CACHEDIR);
- } else {
- alpm_option_set_cachedirs(handle, config->cachedirs);
- }
+ alpm_option_set_cachedirs(handle, config->cachedirs);
 
  alpm_option_set_overwrite_files(handle, config->overwrite_files);
 
  alpm_option_set_default_siglevel(handle, config->siglevel);
 
- config->localfilesiglevel = merge_siglevel(config->siglevel,
- config->localfilesiglevel, config->localfilesiglevel_mask);
- config->remotefilesiglevel = merge_siglevel(config->siglevel,
- config->remotefilesiglevel, config->remotefilesiglevel_mask);
-
  alpm_option_set_local_file_siglevel(handle, config->localfilesiglevel);
  alpm_option_set_remote_file_siglevel(handle, config->remotefilesiglevel);
 
@@ -1036,6 +990,59 @@ static int _parse_directive(const char *file, int linenum, const char *name,
  }
 }
 
+int setdefaults(config_t *c)
+{
+ alpm_list_t *i;
+
+#define SETDEFAULT(opt, val) if(!opt) { opt = val; if(!opt) { return -1; } }
+
+ if(c->rootdir) {
+ char path[PATH_MAX];
+ if(!c->dbpath) {
+ snprintf(path, PATH_MAX, "%s/%s", c->rootdir, DBPATH + 1);
+ SETDEFAULT(c->dbpath, strdup(path));
+ }
+ if(!c->logfile) {
+ snprintf(path, PATH_MAX, "%s/%s", c->rootdir, LOGFILE + 1);
+ SETDEFAULT(c->logfile, strdup(path));
+ }
+ } else {
+ SETDEFAULT(c->rootdir, strdup(ROOTDIR));
+ SETDEFAULT(c->dbpath, strdup(DBPATH));
+ }
+
+ SETDEFAULT(c->logfile, strdup(LOGFILE));
+ SETDEFAULT(c->gpgdir, strdup(GPGDIR));
+ SETDEFAULT(c->cachedirs, alpm_list_add(NULL, strdup(CACHEDIR)));
+ SETDEFAULT(c->hookdirs, alpm_list_add(NULL, strdup(HOOKDIR)));
+ SETDEFAULT(c->cleanmethod, PM_CLEAN_KEEPINST);
+
+ c->localfilesiglevel = merge_siglevel(c->siglevel,
+ c->localfilesiglevel, c->localfilesiglevel_mask);
+ c->remotefilesiglevel = merge_siglevel(c->siglevel,
+ c->remotefilesiglevel, c->remotefilesiglevel_mask);
+
+ for(i = c->repos; i; i = i->next) {
+ config_repo_t *r = i->data;
+ alpm_list_t *j;
+ SETDEFAULT(r->usage, ALPM_DB_USAGE_ALL);
+ r->siglevel = merge_siglevel(c->siglevel, r->siglevel, r->siglevel_mask);
+ for(j = r->servers; j; j = j->next) {
+ char *newurl = replace_server_vars(c, r, j->data);
+ if(newurl == NULL) {
+ return -1;
+ } else {
+ free(j->data);
+ j->data = newurl;
+ }
+ }
+ }
+
+#undef SETDEFAULT
+
+ return 0;
+}
+
 int parseconfigfile(const char *file)
 {
  struct section_t section;
@@ -1054,6 +1061,9 @@ int parseconfig(const char *file)
  if((ret = parseconfigfile(file))) {
  return ret;
  }
+ if((ret = setdefaults(config))) {
+ return ret;
+ }
  pm_printf(ALPM_LOG_DEBUG, "config: finished parsing %s\n", file);
  if((ret = setup_libalpm())) {
  return ret;
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index e937051b..786eec6e 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -243,6 +243,7 @@ void config_repo_free(config_repo_t *repo);
 int config_set_arch(const char *arch);
 int parseconfig(const char *file);
 int parseconfigfile(const char *file);
+int setdefaults(config_t *c);
 #endif /* PM_CONF_H */
 
 /* vim: set noet: */
--
2.15.1
Reply | Threaded
Open this post in threaded view
|

[PATCH 3/4] add pacman-conf utility

Andrew Gregory
In reply to this post by Andrew Gregory
Parsing pacman's configuration file is non-trivial and extremely
difficult to do correctly from scripts; even our own do it incorrectly.
pacman-conf is a dedicated tool specifically to allow scripts to parse
config files, getting the same value that pacman itself would use.

Signed-off-by: Andrew Gregory <[hidden email]>
---
 src/util/.gitignore    |   2 +
 src/util/Makefile.am   |  21 ++-
 src/util/pacman-conf.c | 437 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 458 insertions(+), 2 deletions(-)
 create mode 100644 src/util/pacman-conf.c

diff --git a/src/util/.gitignore b/src/util/.gitignore
index 4cb3103e..3c557cac 100644
--- a/src/util/.gitignore
+++ b/src/util/.gitignore
@@ -2,6 +2,8 @@
 .libs
 cleanupdelta
 cleanupdelta.exe
+pacman-conf
+pacman-conf.exe
 testpkg
 testpkg.exe
 vercmp
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 562151bc..aa812b99 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -3,8 +3,10 @@ conffile  = ${sysconfdir}/pacman.conf
 dbpath    = ${localstatedir}/lib/pacman/
 gpgdir    = ${sysconfdir}/pacman.d/gnupg/
 cachedir  = ${localstatedir}/cache/pacman/pkg/
+logfile   = ${localstatedir}/log/pacman.log
+hookdir   = ${sysconfdir}/pacman.d/hooks/
 
-bin_PROGRAMS = vercmp testpkg cleanupdelta
+bin_PROGRAMS = vercmp testpkg cleanupdelta pacman-conf
 
 AM_CPPFLAGS = \
  -imacros $(top_builddir)/config.h \
@@ -13,7 +15,9 @@ AM_CPPFLAGS = \
  -DCONFFILE=\"$(conffile)\" \
  -DDBPATH=\"$(dbpath)\" \
  -DGPGDIR=\"$(gpgdir)\" \
- -DCACHEDIR=\"$(cachedir)\"
+ -DCACHEDIR=\"$(cachedir)\" \
+ -DHOOKDIR=\"$(hookdir)\" \
+ -DLOGFILE=\"$(logfile)\"
 
 AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS) \
  $(LIBARCHIVE_CFLAGS)
@@ -21,6 +25,19 @@ AM_CFLAGS = -pedantic -D_GNU_SOURCE $(WARNING_CFLAGS) \
 cleanupdelta_SOURCES = cleanupdelta.c
 cleanupdelta_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
 
+pacman_conf_SOURCES = pacman-conf.c \
+ $(top_srcdir)/src/pacman/util.h \
+ $(top_srcdir)/src/pacman/util.c \
+ $(top_srcdir)/src/pacman/ini.h \
+ $(top_srcdir)/src/pacman/ini.c \
+ $(top_srcdir)/src/pacman/util-common.h \
+ $(top_srcdir)/src/pacman/util-common.c \
+ $(top_srcdir)/src/pacman/callback.h \
+ $(top_srcdir)/src/pacman/callback.c \
+ $(top_srcdir)/src/pacman/conf.h \
+ $(top_srcdir)/src/pacman/conf.c
+pacman_conf_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
+
 testpkg_SOURCES = testpkg.c
 testpkg_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
 
diff --git a/src/util/pacman-conf.c b/src/util/pacman-conf.c
new file mode 100644
index 00000000..b2be3e13
--- /dev/null
+++ b/src/util/pacman-conf.c
@@ -0,0 +1,437 @@
+/*
+ *  pacman-conf.c - parse pacman configuration files
+ *
+ *  Copyright (c) 2013-2018 Pacman Development Team <[hidden email]>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include "../pacman/conf.h"
+
+const char *myname = "pacman-conf", *myver = "1.0.0";
+
+alpm_list_t *directives = NULL;
+char sep = '\n', *repo_name = NULL;
+const char *config_file = NULL;
+int repo_list = 0, verbose = 0;
+
+static void cleanup(void)
+{
+ alpm_list_free(directives);
+ config_free(config);
+}
+
+static void usage(int ret)
+{
+ FILE *stream = (ret ? stderr : stdout);
+#define hputs(x) fputs(x"\n", stream)
+ hputs("pacman-conf - query pacman's configuration file");
+ hputs("usage:  pacman-conf [options] [<directive>...]");
+ hputs("        pacman-conf (--repo-list|--help|--version)");
+ hputs("options:");
+ hputs("  --config=<path>  set an alternate configuration file");
+ hputs("  --rootdir=<path> set an alternate installation root");
+ hputs("  --repo=<remote>  query options for a specific repo");
+ hputs("  --verbose        always show directive names");
+ hputs("  --repo-list      list configured repositories");
+ hputs("  --help           display this help information");
+ hputs("  --version        display version information");
+#undef hputs
+ cleanup();
+ exit(ret);
+}
+
+static void parse_opts(int argc, char **argv)
+{
+ int c;
+ config_file = CONFFILE;
+
+ const char *short_opts = "";
+ struct option long_opts[] = {
+ { "config"    , required_argument , NULL , 'c' },
+ { "rootdir"   , required_argument , NULL , 'R' },
+ { "repo"      , required_argument , NULL , 'r' },
+ { "repo-list" , no_argument       , NULL , 'l' },
+ { "verbose"   , no_argument       , NULL , 'v' },
+ { "help"      , no_argument       , NULL , 'h' },
+ { "version"   , no_argument       , NULL , 'V' },
+ { 0, 0, 0, 0 },
+ };
+
+ while((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
+ switch(c) {
+ case 'c':
+ config_file = optarg;
+ break;
+ case 'R':
+ config->rootdir = strdup(optarg);
+ break;
+ case 'l':
+ repo_list = 1;
+ break;
+ case 'r':
+ repo_name = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'h':
+ usage(0);
+ break;
+ case 'V':
+ printf("%s v%s\n", myname, myver);
+ cleanup();
+ exit(0);
+ break;
+ case '?':
+ default:
+ usage(1);
+ break;
+ }
+ }
+
+ if(parseconfigfile(config_file) != 0 || setdefaults(config) != 0) {
+ fprintf(stderr, "error parsing '%s'\n", config_file);
+ }
+}
+
+static void list_repos(void)
+{
+ alpm_list_t *r;
+ for(r = config->repos; r; r = r->next) {
+ config_repo_t *repo = r->data;
+ if(!repo_name || strcmp(repo->name, repo_name) == 0) {
+ printf("%s%c", repo->name, sep);
+ }
+ }
+}
+
+static void show_float(const char *directive, float val)
+{
+ if(verbose) {
+ printf("%s = ", directive);
+ }
+ printf("%f%c", val, sep);
+}
+
+static void show_bool(const char *directive, short unsigned int val)
+{
+ if(val) {
+ printf("%s%c", directive, sep);
+ }
+}
+
+static void show_str(const char *directive, const char *val)
+{
+ if(!val) {
+ return;
+ }
+ if(verbose) {
+ printf("%s = ", directive);
+ }
+ printf("%s%c", val, sep);
+}
+
+static void show_list_str(const char *directive, alpm_list_t *list)
+{
+ alpm_list_t *i;
+ for(i = list; i; i = i->next) {
+ show_str(directive, i->data);
+ }
+}
+
+static void show_cleanmethod(const char *directive, unsigned int method)
+{
+ if(method & PM_CLEAN_KEEPINST) {
+ show_str(directive, "KeepInstalled");
+ }
+ if(method & PM_CLEAN_KEEPCUR) {
+ show_str(directive, "KeepCurrent");
+ }
+}
+
+static void show_siglevel(const char *directive, alpm_siglevel_t level, int pkgonly)
+{
+ if(level == ALPM_SIG_USE_DEFAULT) {
+ return;
+ }
+
+ if(level & ALPM_SIG_PACKAGE) {
+ if(level & ALPM_SIG_PACKAGE_OPTIONAL) {
+ show_str(directive, "PackageOptional");
+ } else {
+ show_str(directive, "PackageRequired");
+ }
+
+ if(level & ALPM_SIG_PACKAGE_UNKNOWN_OK) {
+ show_str(directive, "PackageTrustAll");
+ } else {
+ show_str(directive, "PackageTrustedOnly");
+ }
+ } else {
+ show_str(directive, "PackageNever");
+ }
+
+ if(pkgonly) {
+ return;
+ }
+
+ if(level & ALPM_SIG_DATABASE) {
+ if(level & ALPM_SIG_DATABASE_OPTIONAL) {
+ show_str(directive, "DatabaseOptional");
+ } else {
+ show_str(directive, "DatabaseRequired");
+ }
+
+ if(level & ALPM_SIG_DATABASE_UNKNOWN_OK) {
+ show_str(directive, "DatabaseTrustAll");
+ } else {
+ show_str(directive, "DatabaseTrustedOnly");
+ }
+ } else {
+ show_str(directive, "DatabaseNever");
+ }
+}
+
+static void show_usage(const char *directive, alpm_db_usage_t usage)
+{
+ if(usage & ALPM_DB_USAGE_ALL) {
+ show_str(directive, "All");
+ } else {
+ if(usage & ALPM_DB_USAGE_SYNC) {
+ show_str(directive, "Sync");
+ }
+ if(usage & ALPM_DB_USAGE_SEARCH) {
+ show_str(directive, "Search");
+ }
+ if(usage & ALPM_DB_USAGE_INSTALL) {
+ show_str(directive, "Install");
+ }
+ if(usage & ALPM_DB_USAGE_UPGRADE) {
+ show_str(directive, "Upgrade");
+ }
+ }
+}
+
+static void dump_repo(config_repo_t *repo)
+{
+ show_usage("Usage", repo->usage);
+ show_siglevel("SigLevel", repo->siglevel, 0);
+ show_list_str("Server", repo->servers);
+}
+
+static void dump_config(void)
+{
+ alpm_list_t *i;
+
+ printf("[options]%c", sep);
+
+ show_str("RootDir", config->rootdir);
+ show_str("DBPath", config->dbpath);
+ show_list_str("CacheDir", config->cachedirs);
+ show_list_str("HookDir", config->hookdirs);
+ show_str("GPGDir", config->gpgdir);
+ show_str("LogFile", config->logfile);
+
+ show_list_str("HoldPkg", config->holdpkg);
+ show_list_str("IgnorePkg", config->ignorepkg);
+ show_list_str("IgnoreGroup", config->ignoregrp);
+ show_list_str("NoUpgrade", config->noupgrade);
+ show_list_str("NoExtract", config->noextract);
+
+ show_str("Architecture", config->arch);
+ show_str("XferCommand", config->xfercommand);
+
+ show_bool("UseSyslog", config->usesyslog);
+ show_bool("Color", config->color);
+ show_bool("TotalDownload", config->totaldownload);
+ show_bool("CheckSpace", config->checkspace);
+ show_bool("VerbosePkgLists", config->verbosepkglists);
+ show_bool("ILoveCandy", config->chomp);
+
+ show_float("UseDelta", config->deltaratio);
+
+ show_cleanmethod("CleanMethod", config->cleanmethod);
+
+ show_siglevel("SigLevel", config->siglevel, 0);
+ show_siglevel("LocalFileSigLevel", config->localfilesiglevel, 1);
+ show_siglevel("RemoteFileSigLevel", config->remotefilesiglevel, 1);
+
+ for(i = config->repos; i; i = i->next) {
+ config_repo_t *repo = i->data;
+ printf("[%s]%c", repo->name, sep);
+ dump_repo(repo);
+ }
+}
+
+static int list_repo_directives(void)
+{
+ int ret = 0;
+ alpm_list_t *i;
+ config_repo_t *repo = NULL;
+
+ for(i = config->repos; i; i = i->next) {
+ if(strcmp(repo_name, ((config_repo_t*) i->data)->name) == 0) {
+ repo = i->data;
+ break;
+ }
+ }
+
+ if(!repo) {
+ fprintf(stderr, "error: repo '%s' not configured\n", repo_name);
+ return 1;
+ }
+
+ if(!directives) {
+ dump_repo(repo);
+ return 0;
+ }
+
+ for(i = directives; i; i = i->next) {
+ if(strcasecmp(i->data, "Server") == 0) {
+ show_list_str("Server", repo->servers);
+ } else if(strcasecmp(i->data, "SigLevel") == 0) {
+ show_siglevel("SigLevel", repo->siglevel, 0);
+ } else if(strcasecmp(i->data, "Usage") == 0) {
+ show_usage("Usage", repo->usage);
+ } else if(strcasecmp(i->data, "Include") == 0) {
+ fputs("warning: 'Include' directives cannot be queried\n", stderr);
+ ret = 1;
+ } else {
+ fprintf(stderr, "warning: unknown directive '%s'\n", (char*) i->data);
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+static int list_directives(void)
+{
+ int ret = 0;
+ alpm_list_t *i;
+
+ if(!directives) {
+ dump_config();
+ return 0;
+ }
+
+ for(i = directives; i; i = i->next) {
+ if(strcasecmp(i->data, "RootDir") == 0) {
+ show_str("RootDir", config->rootdir);
+ } else if(strcasecmp(i->data, "DBPath") == 0) {
+ show_str("DBPath", config->dbpath);
+ } else if(strcasecmp(i->data, "CacheDir") == 0) {
+ show_list_str("CacheDir", config->cachedirs);
+ } else if(strcasecmp(i->data, "HookDir") == 0) {
+ show_list_str("HookDir", config->hookdirs);
+ } else if(strcasecmp(i->data, "GPGDir") == 0) {
+ show_str("GPGDir", config->gpgdir);
+ } else if(strcasecmp(i->data, "LogFile") == 0) {
+ show_str("LogFile", config->logfile);
+
+ } else if(strcasecmp(i->data, "HoldPkg") == 0) {
+ show_list_str("HoldPkg", config->holdpkg);
+ } else if(strcasecmp(i->data, "IgnorePkg") == 0) {
+ show_list_str("IgnorePkg", config->ignorepkg);
+ } else if(strcasecmp(i->data, "IgnoreGroup") == 0) {
+ show_list_str("IgnoreGroup", config->ignoregrp);
+ } else if(strcasecmp(i->data, "NoUpgrade") == 0) {
+ show_list_str("NoUpgrade", config->noupgrade);
+ } else if(strcasecmp(i->data, "NoExtract") == 0) {
+ show_list_str("NoExtract", config->noupgrade);
+
+
+ } else if(strcasecmp(i->data, "Architecture") == 0) {
+ show_str("Architecture", config->arch);
+ } else if(strcasecmp(i->data, "XferCommand") == 0) {
+ show_str("XferCommand", config->xfercommand);
+
+ } else if(strcasecmp(i->data, "UseSyslog") == 0) {
+ show_bool("UseSyslog", config->usesyslog);
+ } else if(strcasecmp(i->data, "Color") == 0) {
+ show_bool("Color", config->color);
+ } else if(strcasecmp(i->data, "TotalDownload") == 0) {
+ show_bool("TotalDownload", config->totaldownload);
+ } else if(strcasecmp(i->data, "CheckSpace") == 0) {
+ show_bool("CheckSpace", config->checkspace);
+ } else if(strcasecmp(i->data, "VerbosePkgLists") == 0) {
+ show_bool("VerbosePkgLists", config->verbosepkglists);
+
+ } else if(strcasecmp(i->data, "UseDelta") == 0) {
+ show_float("UseDelta", config->deltaratio);
+
+ } else if(strcasecmp(i->data, "CleanMethod") == 0) {
+ show_cleanmethod("CleanMethod", config->cleanmethod);
+
+ } else if(strcasecmp(i->data, "SigLevel") == 0) {
+ show_siglevel("SigLevel", config->siglevel, 0);
+ } else if(strcasecmp(i->data, "LocalFileSigLevel") == 0) {
+ show_siglevel("LocalFileSigLevel", config->localfilesiglevel, 1);
+ } else if(strcasecmp(i->data, "RemoteFileSigLevel") == 0) {
+ show_siglevel("RemoteFileSigLevel", config->remotefilesiglevel, 1);
+
+ } else if(strcasecmp(i->data, "Include") == 0) {
+ fputs("warning: 'Include' directives cannot be queried\n", stderr);
+ ret = 1;
+ } else {
+ fprintf(stderr, "warning: unknown directive '%s'\n", (char*) i->data);
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret = 0;
+
+ config = config_new();
+ parse_opts(argc, argv);
+ if(!config) {
+ ret = 1;
+ goto cleanup;
+ }
+
+ for(; optind < argc; optind++) {
+ directives = alpm_list_add(directives, argv[optind]);
+ }
+
+ if(alpm_list_count(directives) != 1) {
+ verbose = 1;
+ }
+
+ if(repo_list) {
+ if(directives) {
+ fputs("error: directives may not be specified with --repo-list\n", stderr);
+ ret = 1;
+ goto cleanup;
+ }
+ list_repos();
+ } else if(repo_name) {
+ ret = list_repo_directives();
+ } else {
+ ret = list_directives();
+ }
+
+cleanup:
+ cleanup();
+
+ return ret;
+}
+
+/* vim: set ts=2 sw=2 noet: */
--
2.15.1
Reply | Threaded
Open this post in threaded view
|

[PATCH 4/4] use pacman-conf in scripts

Andrew Gregory
In reply to this post by Andrew Gregory
Because parsing pacman.conf is so difficult that even we can't do it
right.

Signed-off-by: Andrew Gregory <[hidden email]>
---
 scripts/completion/zsh_completion.in |  4 ++--
 scripts/pacman-db-upgrade.sh.in      | 21 ++-------------------
 scripts/pacman-key.sh.in             |  2 +-
 3 files changed, 5 insertions(+), 22 deletions(-)

diff --git a/scripts/completion/zsh_completion.in b/scripts/completion/zsh_completion.in
index f74fa297..77449955 100644
--- a/scripts/completion/zsh_completion.in
+++ b/scripts/completion/zsh_completion.in
@@ -316,7 +316,7 @@ _pacman_completions_all_packages() {
  typeset -U packages
  ${seq} _wanted packages expl "packages" compadd ${sep[@]} - "${(@)packages}"
 
- repositories=(${(o)${${${(M)${(f)"$(<@sysconfdir@/pacman.conf)"}:#\[*}/\[/}/\]/}:#options})
+ repositories=($(pacman-conf --repo-list))
  typeset -U repositories
  _wanted repo_packages expl "repository/package" compadd -S "/" $repositories
  fi
@@ -348,7 +348,7 @@ _pacman_all_packages() {
 # provides completions for repository names
 _pacman_completions_repositories() {
  local -a cmd repositories
- repositories=(${(o)${${${(M)${(f)"$(<@sysconfdir@/pacman.conf)"}:#\[*}/\[/}/\]/}:#options})
+ repositories=($(pacman-conf --repo-list))
  # Uniq the array
  typeset -U repositories
  compadd "$@" -a repositories
diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in
index a6ff3b25..0629cc1c 100644
--- a/scripts/pacman-db-upgrade.sh.in
+++ b/scripts/pacman-db-upgrade.sh.in
@@ -70,18 +70,6 @@ die_r() {
  die "$@"
 }
 
-get_opt_from_config() {
- local keyname="$1" conffile="$2"
- local key value
-
- while IFS=$'= \t' read -r key value _; do
- if [[ $key = $keyname ]]; then
- echo "$value"
- return
- fi
- done <"$conffile"
-}
-
 resolve_dir() {
  local d="$(cd "$1"; pwd -P)"
  [[ $d == */ ]] || d+=/
@@ -121,13 +109,8 @@ while true; do
 done
 
 conffile=${conffile:-@sysconfdir@/pacman.conf}
-[[ -z $pacroot ]] && pacroot="$(get_opt_from_config "RootDir" "$conffile")"
-[[ -z $dbroot ]] && dbroot="$(get_opt_from_config "DBPath" "$conffile")"
-
-[[ -z $dbroot && -n $pacroot ]] && dbroot="$pacroot/@localstatedir@/lib/pacman"
-
-[[ -z $pacroot ]] && pacroot="@rootdir@"
-[[ -z $dbroot ]] && dbroot="@localstatedir@/lib/pacman/"
+[[ -z $pacroot ]] && pacroot=$(pacman-conf --config="$conffile" rootdir)
+[[ -z $dbroot ]] && dbroot=$(pacman-conf --config="$conffile" --rootdir="$pacroot" dbpath)
 
 m4_include(library/term_colors.sh)
 
diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in
index 7b158da7..293a42de 100644
--- a/scripts/pacman-key.sh.in
+++ b/scripts/pacman-key.sh.in
@@ -580,7 +580,7 @@ fi
 
 # if PACMAN_KEYRING_DIR isn't assigned, try to get it from the config
 # file, falling back on a hard default
-PACMAN_KEYRING_DIR=${PACMAN_KEYRING_DIR:-$(get_from "$CONFIG" "GPGDir" "@sysconfdir@/pacman.d/gnupg")}
+PACMAN_KEYRING_DIR=${PACMAN_KEYRING_DIR:-$(pacman-conf --config="$CONFIG" gpgdir)}
 
 GPG_PACMAN=(gpg --homedir "${PACMAN_KEYRING_DIR}" --no-permission-warning)
 if [[ -n ${KEYSERVER} ]]; then
--
2.15.1
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 4/4] use pacman-conf in scripts

Eli Schwartz-2
On 01/13/2018 11:50 AM, Andrew Gregory wrote:
> Because parsing pacman.conf is so difficult that even we can't do it
> right.
>
> Signed-off-by: Andrew Gregory <[hidden email]>
> ---
>  scripts/completion/zsh_completion.in |  4 ++--
>  scripts/pacman-db-upgrade.sh.in      | 21 ++-------------------
>  scripts/pacman-key.sh.in             |  2 +-
>  3 files changed, 5 insertions(+), 22 deletions(-)

Our bash completion should also be updated to use pacman-conf, as
currently it uses a glorious hack to find the completions for -Sl which
involves verbosely printing all packages ever and using `cut|sort -u` to
extract repo names and dedupe them.

Of course, this was still more accurate than the zsh config file parsing.

I'd also like to see some way of listing group names for completing -Qg,
I guess, although that isn't really something to solve via better
*configuration* parsing, so it is probably offtopic for this.

--
Eli Schwartz


signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 4/4] use pacman-conf in scripts

Allan McRae
On 14/01/18 09:21, Eli Schwartz wrote:

> On 01/13/2018 11:50 AM, Andrew Gregory wrote:
>> Because parsing pacman.conf is so difficult that even we can't do it
>> right.
>>
>> Signed-off-by: Andrew Gregory <[hidden email]>
>> ---
>>  scripts/completion/zsh_completion.in |  4 ++--
>>  scripts/pacman-db-upgrade.sh.in      | 21 ++-------------------
>>  scripts/pacman-key.sh.in             |  2 +-
>>  3 files changed, 5 insertions(+), 22 deletions(-)
>
> Our bash completion should also be updated to use pacman-conf, as
> currently it uses a glorious hack to find the completions for -Sl which
> involves verbosely printing all packages ever and using `cut|sort -u` to
> extract repo names and dedupe them.
>

patches welcome.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/4] add pacman-conf utility

Allan McRae
In reply to this post by Andrew Gregory
On 14/01/18 02:49, Andrew Gregory wrote:
> Parsing pacman.conf is so hard that even our own scripts don't do it
> correctly.  pacman-conf is a dedicated utility scripts can use to
> correctly parse values from pacman.conf.  This is a conversion of an
> earlier version of pacconf from pacutils that has been relicensed and
> renamed to avoid a file conflict.  I make no promises that I've
> correctly adjusted the automake configuration for this type of build,
> but it works for me.

Thanks.  I have had a quick look at these and I am very happy!

My quick scan of the automake changes did not flag any issue, but I will
do so in more detail before I commit the changes.  (Reminder to myslef:
make sure "make distcheck" does what it is supposed to.)


We will need a man page (despite the --help output being complete).
This will not prevent these patches being committed, but it will be a
blocker for release.  I assume Andrew has other things in the code base
to look at, so this appears to be a "patches welcome" situation.
Volunteers?

Cheers,
Allan
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 3/4] add pacman-conf utility

Allan McRae
In reply to this post by Andrew Gregory
On 14/01/18 02:49, Andrew Gregory wrote:
> Parsing pacman's configuration file is non-trivial and extremely
> difficult to do correctly from scripts; even our own do it incorrectly.
> pacman-conf is a dedicated tool specifically to allow scripts to parse
> config files, getting the same value that pacman itself would use.
>
> Signed-off-by: Andrew Gregory <[hidden email]>

The automake changes resulted in a big warning that is fixed by enabling
subdir-objects in configure.ac and ignoring the .dirstamp file it creates.

There was also a directory being created in the src/util with the name
'$(top_srcdir)'.  This is due to using a variable in the paths (no idea
why this is an issue), but replacing it with a relative path "fixes" the
issue.

I'll squash the following into your patch:


From 4c3d7964da2ba4276e4464920fb795e9f973e3ec Mon Sep 17 00:00:00 2001
From: Allan McRae <[hidden email]>
Date: Thu, 18 Jan 2018 14:54:17 +1000
Subject: [PATCH] [SQUASH] Fix automake usage for pacman-conf

Signed-off-by: Allan McRae <[hidden email]>
---
 .gitignore           |  1 +
 configure.ac         |  2 +-
 src/util/Makefile.am | 20 ++++++++++----------
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/.gitignore b/.gitignore
index 499d499b..7399a120 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 *~
 *.o
+.dirstamp
 ABOUT-NLS
 aclocal.m4
 autom4te.cache
diff --git a/configure.ac b/configure.ac
index 86f5bb6e..02afba83 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,7 +60,7 @@ AC_CONFIG_AUX_DIR([build-aux])
 AC_REQUIRE_AUX_FILE([tap-driver.sh])

 AC_CANONICAL_HOST
-AM_INIT_AUTOMAKE([1.11 foreign])
+AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
 AM_SILENT_RULES([yes])

 LT_INIT
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index aa812b99..84598ea0 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -26,16 +26,16 @@ cleanupdelta_SOURCES = cleanupdelta.c
 cleanupdelta_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la

 pacman_conf_SOURCES = pacman-conf.c \
- $(top_srcdir)/src/pacman/util.h \
- $(top_srcdir)/src/pacman/util.c \
- $(top_srcdir)/src/pacman/ini.h \
- $(top_srcdir)/src/pacman/ini.c \
- $(top_srcdir)/src/pacman/util-common.h \
- $(top_srcdir)/src/pacman/util-common.c \
- $(top_srcdir)/src/pacman/callback.h \
- $(top_srcdir)/src/pacman/callback.c \
- $(top_srcdir)/src/pacman/conf.h \
- $(top_srcdir)/src/pacman/conf.c
+ ../pacman/util.h \
+ ../pacman/util.c \
+ ../pacman/ini.h \
+ ../pacman/ini.c \
+ ../pacman/util-common.h \
+ ../pacman/util-common.c \
+ ../pacman/callback.h \
+ ../pacman/callback.c \
+ ../pacman/conf.h \
+ ../pacman/conf.c
 pacman_conf_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la

 testpkg_SOURCES = testpkg.c
--
2.15.1
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 3/4] add pacman-conf utility

Allan McRae
On 18/01/18 14:59, Allan McRae wrote:

> On 14/01/18 02:49, Andrew Gregory wrote:
>> Parsing pacman's configuration file is non-trivial and extremely
>> difficult to do correctly from scripts; even our own do it incorrectly.
>> pacman-conf is a dedicated tool specifically to allow scripts to parse
>> config files, getting the same value that pacman itself would use.
>>
>> Signed-off-by: Andrew Gregory <[hidden email]>
>
> The automake changes resulted in a big warning that is fixed by enabling
> subdir-objects in configure.ac and ignoring the .dirstamp file it creates.


Crap... that breaks "make distcheck".  More specifically "make
distclean" as it tries to remove the generated object files for the
common files twice.

> There was also a directory being created in the src/util with the name
> '$(top_srcdir)'.  This is due to using a variable in the paths (no idea
> why this is an issue), but replacing it with a relative path "fixes" the
> issue.
>
> I'll squash the following into your patch:
>
>
>>From 4c3d7964da2ba4276e4464920fb795e9f973e3ec Mon Sep 17 00:00:00 2001
> From: Allan McRae <[hidden email]>
> Date: Thu, 18 Jan 2018 14:54:17 +1000
> Subject: [PATCH] [SQUASH] Fix automake usage for pacman-conf
>
> Signed-off-by: Allan McRae <[hidden email]>
> ---
>  .gitignore           |  1 +
>  configure.ac         |  2 +-
>  src/util/Makefile.am | 20 ++++++++++----------
>  3 files changed, 12 insertions(+), 11 deletions(-)
>
> diff --git a/.gitignore b/.gitignore
> index 499d499b..7399a120 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -1,5 +1,6 @@
>  *~
>  *.o
> +.dirstamp
>  ABOUT-NLS
>  aclocal.m4
>  autom4te.cache
> diff --git a/configure.ac b/configure.ac
> index 86f5bb6e..02afba83 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -60,7 +60,7 @@ AC_CONFIG_AUX_DIR([build-aux])
>  AC_REQUIRE_AUX_FILE([tap-driver.sh])
>
>  AC_CANONICAL_HOST
> -AM_INIT_AUTOMAKE([1.11 foreign])
> +AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
>  AM_SILENT_RULES([yes])
>
>  LT_INIT
> diff --git a/src/util/Makefile.am b/src/util/Makefile.am
> index aa812b99..84598ea0 100644
> --- a/src/util/Makefile.am
> +++ b/src/util/Makefile.am
> @@ -26,16 +26,16 @@ cleanupdelta_SOURCES = cleanupdelta.c
>  cleanupdelta_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
>
>  pacman_conf_SOURCES = pacman-conf.c \
> - $(top_srcdir)/src/pacman/util.h \
> - $(top_srcdir)/src/pacman/util.c \
> - $(top_srcdir)/src/pacman/ini.h \
> - $(top_srcdir)/src/pacman/ini.c \
> - $(top_srcdir)/src/pacman/util-common.h \
> - $(top_srcdir)/src/pacman/util-common.c \
> - $(top_srcdir)/src/pacman/callback.h \
> - $(top_srcdir)/src/pacman/callback.c \
> - $(top_srcdir)/src/pacman/conf.h \
> - $(top_srcdir)/src/pacman/conf.c
> + ../pacman/util.h \
> + ../pacman/util.c \
> + ../pacman/ini.h \
> + ../pacman/ini.c \
> + ../pacman/util-common.h \
> + ../pacman/util-common.c \
> + ../pacman/callback.h \
> + ../pacman/callback.c \
> + ../pacman/conf.h \
> + ../pacman/conf.c
>  pacman_conf_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la
>
>  testpkg_SOURCES = testpkg.c
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 3/4] add pacman-conf utility

Allan McRae
On 18/01/18 15:29, Allan McRae wrote:

> On 18/01/18 14:59, Allan McRae wrote:
>> On 14/01/18 02:49, Andrew Gregory wrote:
>>> Parsing pacman's configuration file is non-trivial and extremely
>>> difficult to do correctly from scripts; even our own do it incorrectly.
>>> pacman-conf is a dedicated tool specifically to allow scripts to parse
>>> config files, getting the same value that pacman itself would use.
>>>
>>> Signed-off-by: Andrew Gregory <[hidden email]>
>>
>> The automake changes resulted in a big warning that is fixed by enabling
>> subdir-objects in configure.ac and ignoring the .dirstamp file it creates.
>
>
> Crap... that breaks "make distcheck".  More specifically "make
> distclean" as it tries to remove the generated object files for the
> common files twice.

Turns out automake with this subdir-objects option (which will become
default next release) is buggy as hell.  Some patches have landed
upstream, but we can't rely on them in the pacman codebase.

Options here....

1) host pacman-conf in the src/pacman directory

2) Use the makefile to copy the needed src/pacman files into
src/util/pacman-conf/... and they get compiled twice.

3) create a small library using the needed files and static link it into
pacman-conf


To be clear, I only included #3 as I saw several projects do this!


I see #1 as the easiest. And probably most correct - the overlap in
source used here is such that they should be located in the same place.

Allan