[pacman-dev] attempt of reworking pacman_query function
looking at the current code in src/query.c , I found it could be more flexible, and that some parts could be refactored a bit. I think there should be a distinction in the code between "filter" options, like --orphans or --foreign, and display options, like -Qi, -Qii or -Ql. The code for displaying the output (depending on i, l options) was at 3 different places of query.c , so I moved all in a display(pmpkg_t *) function. I also merged the query_isfile function in the main loop of pacman_query. Also, the orphans and foreign functions had their own loop walking through the list of targets, besides the one in pacman_query(). So I made new functions : filter(pkg), is_orphan(pkg) and is_foreign(pkg) that determine if a package should be displayed or not when these options are used. After this, it should be easier to add --explicit and --depend options for displaying only explictly installed packages, or only packages installed as dependencies. Also, it would be much easier and cleaner if the orphans option displayed all packages not required by any other by default, and then you could get dependencies only by using another flag. That's done by my patch, and if it's ok, I'll be able to very easily add the two new options above. That would allow to keep the code as clean as possible, while still getting as much configurabily as we want without any confusion. Some examples : pacman -Qe : lists all explictly installed packages pacman -Qd : list all packages installed as dependencies pacman -Qt : list all orphans (package not required by any others) pacman -Qtd : list real orphans (package installed as dependencies, but not required by any others anymore) (that is the current orphan option) pacman -Qte : list package explicitly installed and not required by any others (pacman2 orphan option). So the following patch does not add e and d options yet, it just prepare for them :)
From 31d6c53de9d680046c2c610fe5382173e11c7950 Mon Sep 17 00:00:00 2001 From: Chantry Xavier <shiningxc@gmail.com> Date: Sat, 14 Jul 2007 20:45:30 +0200 Subject: [PATCH] libalpm/query.c : makes orphans and foreign options as filters.
The --foreign and --orphans functions now behave as a filter for the other options. This cleans the code a bit, and will make easier the adding of new filter options, like explicit (show only explictly installed packages) or depends (show only packages installed as dependencies). Signed-off-by: Chantry Xavier <shiningxc@gmail.com> --- src/pacman/query.c | 205 +++++++++++++++++++--------------------------------- 1 files changed, 76 insertions(+), 129 deletions(-) diff --git a/src/pacman/query.c b/src/pacman/query.c index f6c6b5d..de118e7 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -211,41 +211,6 @@ static int query_group(alpm_list_t *targets) return ret; } -static int query_isfile(alpm_list_t *targets) -{ - int ret = 0; - char *package = NULL; - alpm_list_t *i; - pmpkg_t *info = NULL; - if(targets == NULL) { - fprintf(stderr, _("error: no package file was specified for --file\n")); - return(1); - } else { - for(i = targets; i; i = alpm_list_next(i)) { - package = alpm_list_getdata(i); - if(alpm_pkg_load(package, &info) == -1) { - fprintf(stderr, _("error: failed to load package '%s' (%s)\n"), - package, alpm_strerror(pm_errno)); - ret++; - continue; - } - if(config->op_q_info) { - dump_pkg_full(info, config->op_q_info); - } - if(config->op_q_list) { - dump_pkg_files(info); - } - if(!config->op_q_info && !config->op_q_list) { - printf("%s %s\n", alpm_pkg_get_name(info), - alpm_pkg_get_version(info)); - } - alpm_pkg_free(info); - info = NULL; - } - } - return(ret); -} - static int query_test(void) { int ret = 0; @@ -283,59 +248,69 @@ static int query_upgrades(void) return(1); } -static int query_foreign(void) +static int is_foreign(pmpkg_t *pkg) { - alpm_list_t *sync_dbs = NULL; - alpm_list_t *i; - - /* ensure we have at least one valid sync db set up */ - sync_dbs = alpm_option_get_syncdbs(); - if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) { - pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); + const char *pkgname = alpm_pkg_get_name(pkg); + alpm_list_t *j; + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + + int match = 0; + for(j = sync_dbs; j; j = alpm_list_next(j)) { + pmdb_t *db = alpm_list_getdata(j); + pmpkg_t *pkg = alpm_db_get_pkg(db, pkgname); + if(pkg) { + match = 1; + break; + } + } + if(match == 0) { return(1); } + return(0); +} - for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) { - pmpkg_t *pkg = alpm_list_getdata(i); - const char *pkgname = alpm_pkg_get_name(pkg); - const char *pkgver = alpm_pkg_get_version(pkg); - alpm_list_t *j; - - int match = 0; - for(j = sync_dbs; j; j = alpm_list_next(j)) { - pmdb_t *db = alpm_list_getdata(j); - pmpkg_t *pkg = alpm_db_get_pkg(db, pkgname); - if(pkg) { - match = 1; - break; - } - } - if(match == 0) { - printf("%s %s\n", pkgname, pkgver); - } +static int is_orphan(pmpkg_t *pkg) +{ + if(alpm_pkg_get_requiredby(pkg) == NULL) { + return(1); } return(0); } -static int query_orphans(void) +static int filter(pmpkg_t *pkg) { - alpm_list_t *i; + /* check if this pkg isn't in a sync DB */ + if(config->op_q_foreign && !is_foreign(pkg)) { + return(0); + } + /* check if this pkg is orphaned */ + if(config->op_q_orphans && !is_orphan(pkg)) { + return(0); + } + return(1); +} - for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) { - pmpkg_t *pkg = alpm_list_getdata(i); - const char *pkgname = alpm_pkg_get_name(pkg); - const char *pkgver = alpm_pkg_get_version(pkg); - - /* two cases here: - * 1. one -e option was specified, return only those installed as dep - * 2. more than one -e specified, return all with empty requiredby */ - if(alpm_pkg_get_requiredby(pkg) == NULL - && (alpm_pkg_get_reason(pkg) == PM_PKG_REASON_DEPEND - || config->op_q_orphans > 1)) { - printf("%s %s\n", pkgname, pkgver); - } +static void display(pmpkg_t *pkg) +{ + if(config->op_q_info) { + dump_pkg_full(pkg, config->op_q_info); + } + if(config->op_q_list) { + dump_pkg_files(pkg); + } + if(config->op_q_changelog) { + char changelog[PATH_MAX]; + /* TODO should be done in the backend- no raw DB stuff up front */ + snprintf(changelog, PATH_MAX, "%s/%s/%s-%s/changelog", + alpm_option_get_dbpath(), + alpm_db_get_name(db_local), + alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg)); + dump_pkg_changelog(changelog, alpm_pkg_get_name(pkg)); + } + if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) { + printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); } - return(0); } int pacman_query(alpm_list_t *targets) @@ -369,35 +344,28 @@ int pacman_query(alpm_list_t *targets) return(ret); } - /* search for installed packages not in a sync DB */ if(config->op_q_foreign) { - ret = query_foreign(); - return(ret); - } - - /* list orphaned packages */ - if(config->op_q_orphans) { - ret = query_orphans(); - return(ret); + /* ensure we have at least one valid sync db set up */ + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) { + pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); + return(-1); + } } /* operations on all packages in the local DB * valid: no-op (plain -Q), list, info * invalid: isfile, owns */ - if(targets == NULL && !(config->op_q_isfile || config->op_q_owns)) { + if(targets == NULL) { + if(config->op_q_isfile || config->op_q_owns) { + pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); + return(1); + } + for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) { pmpkg_t *pkg = alpm_list_getdata(i); - const char *pkgname = alpm_pkg_get_name(pkg); - const char *pkgver = alpm_pkg_get_version(pkg); - - if(config->op_q_info) { - dump_pkg_full(pkg, config->op_q_info); - } - if(config->op_q_list) { - dump_pkg_files(pkg); - } - if(!config->op_q_info && !config->op_q_list) { - printf("%s %s\n", pkgname, pkgver); + if(filter(pkg)) { + display(pkg); } } return(0); @@ -405,17 +373,6 @@ int pacman_query(alpm_list_t *targets) /* Second: operations that require target(s) */ - if(targets == NULL) { - pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); - return(1); - } - - /* output info for a .tar.gz package */ - if(config->op_q_isfile) { - ret = query_isfile(targets); - return(ret); - } - /* determine the owner of a file */ if(config->op_q_owns) { ret = query_fileowner(targets); @@ -426,32 +383,22 @@ int pacman_query(alpm_list_t *targets) * valid: no-op (plain -Q), list, info */ for(i = targets; i; i = alpm_list_next(i)) { char *strname = alpm_list_getdata(i); - pmpkg_t *pkg = alpm_db_get_pkg(db_local, strname); + pmpkg_t *pkg = NULL; + + if(config->op_q_isfile) { + alpm_pkg_load(strname, &pkg); + } else { + pkg = alpm_db_get_pkg(db_local, strname); + } + if(pkg == NULL) { fprintf(stderr, _("error: package \"%s\" not found\n"), strname); ret++; continue; } - /* find a target */ - if(config->op_q_info) { - dump_pkg_full(pkg, config->op_q_info); - } - if(config->op_q_list) { - dump_pkg_files(pkg); - } - if(config->op_q_changelog) { - char changelog[PATH_MAX]; - /* TODO should be done in the backend- no raw DB stuff up front */ - snprintf(changelog, PATH_MAX, "%s/%s/%s-%s/changelog", - alpm_option_get_dbpath(), - alpm_db_get_name(db_local), - alpm_pkg_get_name(pkg), - alpm_pkg_get_version(pkg)); - dump_pkg_changelog(changelog, alpm_pkg_get_name(pkg)); - } - if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) { - printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + if(filter(pkg)) { + display(pkg); } } -- 1.5.2.2
On Sat, Jul 14, 2007 at 09:20:45PM +0200, Xavier wrote:
Some examples : pacman -Qe : lists all explictly installed packages pacman -Qd : list all packages installed as dependencies pacman -Qt : list all orphans (package not required by any others) pacman -Qtd : list real orphans (package installed as dependencies, but not required by any others anymore) (that is the current orphan option) pacman -Qte : list package explicitly installed and not required by any others (pacman2 orphan option).
So the following patch does not add e and d options yet, it just prepare for them :)
here is the missing bit :
From 027f0977451406cdc8e430b1b9b7b234c091ff07 Mon Sep 17 00:00:00 2001 From: Chantry Xavier <shiningxc@gmail.com> Date: Sun, 15 Jul 2007 00:44:06 +0200 Subject: [PATCH] new query options : explicit (-Qe) and deps (-Qd).
The t shortcut for --test was removed, the orphan option (previously -Qe) was renamed to -Qt, -Qe lists all packages installed explictly, and -Qd lists all packages installed as dependencies. Besides, t can be combined with either e or d. Signed-off-by: Chantry Xavier <shiningxc@gmail.com> --- src/pacman/conf.h | 2 ++ src/pacman/pacman.c | 25 +++++++++++++++++-------- src/pacman/query.c | 10 ++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 252bb95..68defa9 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -42,6 +42,8 @@ typedef struct __config_t { unsigned short op_q_list; unsigned short op_q_foreign; unsigned short op_q_orphans; + unsigned short op_q_deps; + unsigned short op_q_explicit; unsigned short op_q_owns; unsigned short op_q_search; unsigned short op_q_changelog; diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 5281df6..e709329 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -112,8 +112,9 @@ static void usage(int op, char *myname) printf("%s: %s {-Q --query} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg); printf("%s:\n", str_opt); printf(_(" -c, --changelog view the changelog of a package\n")); - printf(_(" -e, --orphans list all packages installed as dependencies but no longer\n" - " required by any package\n")); + printf(_(" -t, --orphans list all packages not required by any package\n")); + printf(_(" -e, --explicit list all packages explicitly installed\n")); + printf(_(" -d, --deps list all packages installed as dependencies\n")); printf(_(" -g, --groups view all members of a package group\n")); printf(_(" -i, --info view package information\n")); printf(_(" -l, --list list the contents of the queried package\n")); @@ -121,7 +122,7 @@ static void usage(int op, char *myname) printf(_(" -o, --owns <file> query the package that owns <file>\n")); printf(_(" -p, --file <package> query a package file instead of the database\n")); printf(_(" -s, --search <regex> search locally-installed packages for matching strings\n")); - printf(_(" -t, --test check the consistency of the local database\n")); + printf(_(" --test check the consistency of the local database\n")); printf(_(" -u, --upgrades list all packages that can be upgraded\n")); } else if(op == PM_OP_SYNC) { printf("%s: %s {-S --sync} [%s] [%s]\n", str_usg, myname, str_opt, str_pkg); @@ -262,8 +263,9 @@ static int parseargs(int argc, char *argv[]) {"changelog", no_argument, 0, 'c'}, {"clean", no_argument, 0, 'c'}, {"nodeps", no_argument, 0, 'd'}, + {"deps", no_argument, 0, 'd'}, {"dependsonly",no_argument, 0, 'e'}, - {"orphans", no_argument, 0, 'e'}, + {"explicit", no_argument, 0, 'e'}, {"force", no_argument, 0, 'f'}, {"groups", no_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, @@ -278,7 +280,7 @@ static int parseargs(int argc, char *argv[]) {"root", required_argument, 0, 'r'}, {"recursive", no_argument, 0, 's'}, {"search", no_argument, 0, 's'}, - {"test", no_argument, 0, 't'}, + {"orphans", no_argument, 0, 't'}, {"upgrades", no_argument, 0, 'u'}, {"sysupgrade", no_argument, 0, 'u'}, {"verbose", no_argument, 0, 'v'}, @@ -292,6 +294,7 @@ static int parseargs(int argc, char *argv[]) {"noscriptlet", no_argument, 0, 1005}, {"ask", required_argument, 0, 1006}, {"cachedir", required_argument, 0, 1007}, + {"test", no_argument, 0, 1008}, {0, 0, 0, 0} }; struct stat st; @@ -345,6 +348,9 @@ static int parseargs(int argc, char *argv[]) } alpm_option_add_cachedir(optarg); break; + case 1008: + config->op_q_test = 1; + break; case 'A': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_ADD); break; case 'F': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_UPGRADE); @@ -369,9 +375,12 @@ static int parseargs(int argc, char *argv[]) config->flags |= PM_TRANS_FLAG_CASCADE; config->op_q_changelog = 1; break; - case 'd': config->flags |= PM_TRANS_FLAG_NODEPS; break; + case 'd': + config->op_q_deps = 1; + config->flags |= PM_TRANS_FLAG_NODEPS; + break; case 'e': - config->op_q_orphans++; + config->op_q_explicit = 1; config->flags |= PM_TRANS_FLAG_DEPENDSONLY; break; case 'f': config->flags |= PM_TRANS_FLAG_FORCE; break; @@ -401,7 +410,7 @@ static int parseargs(int argc, char *argv[]) config->flags |= PM_TRANS_FLAG_RECURSE; break; case 't': - config->op_q_test = 1; + config->op_q_orphans = 1; break; case 'u': config->op_s_upgrade = 1; diff --git a/src/pacman/query.c b/src/pacman/query.c index de118e7..b74a0c0 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -279,6 +279,16 @@ static int is_orphan(pmpkg_t *pkg) static int filter(pmpkg_t *pkg) { + /* check if this package was explicitly installed */ + if(config->op_q_explicit && + alpm_pkg_get_reason(pkg) != PM_PKG_REASON_EXPLICIT) { + return(0); + } + /* check if this package was installed as a dependency */ + if(config->op_q_deps && + alpm_pkg_get_reason(pkg) != PM_PKG_REASON_DEPEND) { + return(0); + } /* check if this pkg isn't in a sync DB */ if(config->op_q_foreign && !is_foreign(pkg)) { return(0); -- 1.5.2.2
participants (1)
-
Xavier