1 Dec
2011
1 Dec
'11
3:42 a.m.
On Wed, Nov 23, 2011 at 9:51 AM, Benedikt Morbach <benedikt.morbach@googlemail.com> wrote: > Signed-off-by: Benedikt Morbach <benedikt.morbach@googlemail.com> > --- > doc/pacman.8.txt | 6 ++++++ > lib/libalpm/alpm.h | 2 +- > lib/libalpm/package.c | 33 +++++++++++++++++++++++---------- > src/pacman/conf.h | 1 + > src/pacman/package.c | 2 +- > src/pacman/pacman.c | 3 +++ > src/pacman/query.c | 16 +++++++++++++--- > src/util/pactree.c | 2 +- > test/pacman/tests/query020.py | 14 ++++++++++++++ > test/pacman/tests/query021.py | 14 ++++++++++++++ > 10 files changed, 77 insertions(+), 16 deletions(-) > create mode 100644 test/pacman/tests/query020.py > create mode 100644 test/pacman/tests/query021.py > > diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt > index 39551e1..62dd908 100644 > --- a/doc/pacman.8.txt > +++ b/doc/pacman.8.txt > @@ -280,6 +280,12 @@ Query Options[[QO]] > database(s). Typically these are packages that were downloaded manually > and installed with '\--upgrade'. > > +*-n, \--optdeps*:: > + When using the '-t' option with this flag, do not treat installed > + optional dependencies as if they were normal dependencies. This option > + can be used to list packages which were installed as dependencies but are > + only optionally used by other packages. > + > *-o, \--owns* <file>:: > Search for packages that own the specified file(s). The path can be > relative or absolute and one or more files can be specified. > diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h > index 943ceec..d06ad0d 100644 > --- a/lib/libalpm/alpm.h > +++ b/lib/libalpm/alpm.h > @@ -715,7 +715,7 @@ int alpm_pkg_vercmp(const char *a, const char *b); > * @param pkg a package > * @return the list of packages requiring pkg > */ > -alpm_list_t *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg); > +alpm_list_t *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg, const int find_optdeps); 1. You didn't add the new param to the documentation 2. This is definitely not self-documenting; when I looked at the code I was completely surprised to find it either finds depends OR optdepends, but not both. I'm honestly not sure overloading this *public* method makes sense. Given you ask for alpm_pkg_get_depends() or alpm_pkg_get_optdepends(), I would expect the reciprocals to also have two methods. Something like alpm_pkg_compute_requiredby() and alpm_pkg_compute_optrequiredby(). > /** @name Package Property Accessors > * Any pointer returned by these functions points to internal structures > diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c > index 451506b..3c217b7 100644 > --- a/lib/libalpm/package.c > +++ b/lib/libalpm/package.c > @@ -382,7 +382,8 @@ int SYMEXPORT alpm_pkg_has_scriptlet(alpm_pkg_t *pkg) > return pkg->ops->has_scriptlet(pkg); > } > > -static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs) > +static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, > + alpm_list_t **reqs, const int find_optdeps) Making the int const here doesn't really help much; we don't tend to do this in any of our functions. > { > const alpm_list_t *i; > pkg->handle->pm_errno = 0; > @@ -390,11 +391,23 @@ static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs) > for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { > alpm_pkg_t *cachepkg = i->data; > alpm_list_t *j; > - for(j = alpm_pkg_get_depends(cachepkg); j; j = j->next) { > - if(_alpm_depcmp(pkg, j->data)) { > - const char *cachepkgname = cachepkg->name; > - if(alpm_list_find_str(*reqs, cachepkgname) == NULL) { > - *reqs = alpm_list_add(*reqs, strdup(cachepkgname)); > + if(find_optdeps) { > + for(j = alpm_pkg_get_optdepends(cachepkg); j; j = j->next) { > + alpm_optdepend_t *optdep = j->data; > + if(_alpm_depcmp(pkg, optdep->depend)) { > + const char *cachepkgname = cachepkg->name; > + if(alpm_list_find_str(*reqs, cachepkgname) == NULL) { > + *reqs = alpm_list_add(*reqs, strdup(cachepkgname)); > + } > + } > + } > + } else { > + for(j = alpm_pkg_get_depends(cachepkg); j; j = j->next) { > + if(_alpm_depcmp(pkg, j->data)) { > + const char *cachepkgname = cachepkg->name; > + if(alpm_list_find_str(*reqs, cachepkgname) == NULL) { > + *reqs = alpm_list_add(*reqs, strdup(cachepkgname)); > + } This won't have to change near as much if both are the same type; simply initialize j based on find_optdeps() and keep the rest of the loop body intact and unchanged indent. > } > } > } > @@ -402,7 +415,7 @@ static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs) > } > > /** Compute the packages requiring a given package. */ > -alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg) > +alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg, const int find_optdeps) > { > const alpm_list_t *i; > alpm_list_t *reqs = NULL; > @@ -413,17 +426,17 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg) > > if(pkg->origin == PKG_FROM_FILE) { > /* The sane option; search locally for things that require this. */ > - find_requiredby(pkg, pkg->handle->db_local, &reqs); > + find_requiredby(pkg, pkg->handle->db_local, &reqs, find_optdeps); > } else { > /* We have a DB package. if it is a local package, then we should > * only search the local DB; else search all known sync databases. */ > db = pkg->origin_data.db; > if(db->status & DB_STATUS_LOCAL) { > - find_requiredby(pkg, db, &reqs); > + find_requiredby(pkg, db, &reqs, find_optdeps); > } else { > for(i = pkg->handle->dbs_sync; i; i = i->next) { > db = i->data; > - find_requiredby(pkg, db, &reqs); > + find_requiredby(pkg, db, &reqs, find_optdeps); > } > reqs = alpm_list_msort(reqs, alpm_list_count(reqs), _alpm_str_cmp); > } > diff --git a/src/pacman/conf.h b/src/pacman/conf.h > index 7ff37ff..9858f7d 100644 > --- a/src/pacman/conf.h > +++ b/src/pacman/conf.h > @@ -54,6 +54,7 @@ typedef struct __config_t { > unsigned short op_q_unrequired; > unsigned short op_q_deps; > unsigned short op_q_explicit; > + unsigned short op_q_optdeps; > unsigned short op_q_owns; > unsigned short op_q_search; > unsigned short op_q_changelog; > diff --git a/src/pacman/package.c b/src/pacman/package.c > index 49192bf..642307c 100644 > --- a/src/pacman/package.c > +++ b/src/pacman/package.c > @@ -109,7 +109,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) > > if(extra || from == PKG_FROM_LOCALDB) { > /* compute this here so we don't get a pause in the middle of output */ > - requiredby = alpm_pkg_compute_requiredby(pkg); > + requiredby = alpm_pkg_compute_requiredby(pkg, 0); > } > > /* actual output */ > diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c > index fa35e8d..fd93133 100644 > --- a/src/pacman/pacman.c > +++ b/src/pacman/pacman.c > @@ -145,6 +145,7 @@ static void usage(int op, const char * const myname) > addlist(_(" -k, --check check that the files owned by the package(s) are present\n")); > addlist(_(" -l, --list list the contents of the queried package\n")); > addlist(_(" -m, --foreign list installed packages not found in sync db(s) [filter]\n")); > + addlist(_(" -n, --optdeps don't consider installed optdepends to be required\n")); > addlist(_(" -o, --owns <file> query the package that owns <file>\n")); > addlist(_(" -p, --file <package> query a package file instead of the database\n")); > addlist(_(" -q, --quiet show less information for query and search\n")); > @@ -461,6 +462,7 @@ static int parsearg_query(int opt) > case 'c': config->op_q_changelog = 1; break; > case 'd': config->op_q_deps = 1; break; > case 'e': config->op_q_explicit = 1; break; > + case 'n': config->op_q_optdeps = 1; break; > case 'g': (config->group)++; break; > case 'i': (config->op_q_info)++; break; > case 'k': config->op_q_check = 1; break; > @@ -603,6 +605,7 @@ static int parseargs(int argc, char *argv[]) > {"list", no_argument, 0, 'l'}, > {"foreign", no_argument, 0, 'm'}, > {"nosave", no_argument, 0, 'n'}, > + {"optdeps", no_argument, 0, 'n'}, -2 on using 'n' for the shortopt here: -1) Doubling the meaning of -n -2) This seems like a very useful and implementable flag down the line for -R, similar to existing -c and -s, but you have precluded this by choosing -n. Also, the name '--optdepts' is quite deceiving, as it seems specifying it makes pacman *ignore* them rather than include them. Quite odd from an outside perspective. > {"owns", no_argument, 0, 'o'}, > {"file", no_argument, 0, 'p'}, > {"print", no_argument, 0, 'p'}, > diff --git a/src/pacman/query.c b/src/pacman/query.c > index 4c2ea81..fbff341 100644 > --- a/src/pacman/query.c > +++ b/src/pacman/query.c > @@ -363,9 +363,15 @@ static int is_foreign(alpm_pkg_t *pkg) > return 0; > } > > -static int is_unrequired(alpm_pkg_t *pkg) > +static int is_unrequired(alpm_pkg_t *pkg, const int find_optdeps) > { > - alpm_list_t *requiredby = alpm_pkg_compute_requiredby(pkg); > + alpm_list_t *requiredby; > + if(find_optdeps) { > + requiredby = alpm_pkg_compute_requiredby(pkg, 1); > + } else { > + requiredby = alpm_pkg_compute_requiredby(pkg, 0); > + } > + > if(requiredby == NULL) { > return 1; > } > @@ -390,7 +396,11 @@ static int filter(alpm_pkg_t *pkg) > return 0; > } > /* check if this pkg is unrequired */ > - if(config->op_q_unrequired && !is_unrequired(pkg)) { > + if(config->op_q_unrequired && !is_unrequired(pkg, 0)) { > + return 0; > + } > + /* check if this pkg is optionally required */ > + if(config->op_q_unrequired && !config->op_q_optdeps && !is_unrequired(pkg, 1)) { > return 0; > } > /* check if this pkg is outdated */ > diff --git a/src/util/pactree.c b/src/util/pactree.c > index f95c5e8..700bfe8 100644 > --- a/src/util/pactree.c > +++ b/src/util/pactree.c > @@ -383,7 +383,7 @@ static void walk_reverse_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, int depth) > } > > walked = alpm_list_add(walked, (void *)alpm_pkg_get_name(pkg)); > - required_by = alpm_pkg_compute_requiredby(pkg); > + required_by = alpm_pkg_compute_requiredby(pkg, 0); > > for(i = required_by; i; i = alpm_list_next(i)) { > const char *pkgname = i->data; > diff --git a/test/pacman/tests/query020.py b/test/pacman/tests/query020.py > new file mode 100644 > index 0000000..a6c8ffe > --- /dev/null > +++ b/test/pacman/tests/query020.py > @@ -0,0 +1,14 @@ > +self.description = "Query unneeded deps (installed optdeps required)" > + > +p1 = pmpkg("dummy", "1.0-2") > +p1.optdepends = ["dep: for foobar"] > +self.addpkg2db("local", p1) > + > +p2 = pmpkg("dep") > +p2.reason = 1 > +self.addpkg2db("local", p2) > + > +self.args = "-Qtd" > + > +self.addrule("PACMAN_RETCODE=1") > +self.addrule("!PACMAN_OUTPUT=^dep") > diff --git a/test/pacman/tests/query021.py b/test/pacman/tests/query021.py > new file mode 100644 > index 0000000..1a0ad40 > --- /dev/null > +++ b/test/pacman/tests/query021.py > @@ -0,0 +1,14 @@ > +self.description = "Query unneeded deps (installed optdeps not required)" > + > +p1 = pmpkg("dummy", "1.0-2") > +p1.optdepends = ["dep: for foobar"] > +self.addpkg2db("local", p1) > + > +p2 = pmpkg("dep") > +p2.reason = 1 > +self.addpkg2db("local", p2) > + > +self.args = "-Qtdn" > + > +self.addrule("PACMAN_RETCODE=0") > +self.addrule("PACMAN_OUTPUT=^dep") > -- > 1.7.7.3 > >