pactree: Add support for getting optional dependencies

Message ID 20200504181120.17766-1-frederick888@tsundere.moe
State Changes Requested
Delegated to: Johannes Löthberg
Headers show
Series
  • pactree: Add support for getting optional dependencies
Related show

Commit Message

Frederick Zhang May 4, 2020, 6:11 p.m. UTC
Patch by Johannes Löthberg [1] with minor modifications

[1] https://lists.archlinux.org/pipermail/pacman-dev/2016-February/020922.html

Signed-off-by: Frederick Zhang <frederick888@tsundere.moe>
---

It probably got lost and was never merged according to the discussion I
just had with Eli in pacman-dev.

Credits to Johannes. I made a few minor changes to make it compile.

 doc/pactree.8.txt |  3 +++
 src/pactree.c     | 34 ++++++++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 4 deletions(-)

Comments

Johannes Löthberg May 26, 2020, 7:55 p.m. UTC | #1
Excerpts from Frederick Zhang's message of May 4, 2020 20:11:
> Patch by Johannes Löthberg [1] with minor modifications
> 
> [1] https://lists.archlinux.org/pipermail/pacman-dev/2016-February/020922.html
> 
> Signed-off-by: Frederick Zhang <frederick888@tsundere.moe>
> ---
> 
> It probably got lost and was never merged according to the discussion I
> just had with Eli in pacman-dev.
> 
> Credits to Johannes. I made a few minor changes to make it compile.
> 

Hey,

Sorry for the late reply, been too busy...

The reason that it was never merged is that it doesn't work properly.  
The problem is that while it works fine for -so, when searching for 
local packages it should properly exclude optional dependencies that are 
not installed so they're not printed, rather than being printed as 
unresolvable.

Patch

diff --git a/doc/pactree.8.txt b/doc/pactree.8.txt
index 296d04e..c8666ad 100644
--- a/doc/pactree.8.txt
+++ b/doc/pactree.8.txt
@@ -48,8 +48,11 @@  Options
 
 *-l, \--linear*::
 	Prints package names at the start of each line, one per line.
 
+*-o, \--optdeps*::
+	Show packages that are optionally depended upon by the named package.
+
 *-r, \--reverse*::
 	Show packages that depend on the named package.
 
 *-s, \--sync*::
diff --git a/src/pactree.c b/src/pactree.c
index cf83326..6da4294 100644
--- a/src/pactree.c
+++ b/src/pactree.c
@@ -119,8 +119,9 @@  static alpm_list_t *provisions = NULL;
 static struct color_choices *color = &no_color;
 static struct graph_style *style = &graph_utf8;
 static int graphviz = 0;
 static int max_depth = -1;
+static int optdeps = 0;
 static int reverse = 0;
 static int unique = 0;
 static int searchsyncs = 0;
 static int debug = 0;
@@ -249,8 +250,9 @@  static void usage(void)
 			"  -d, --depth <#>      limit the depth of recursion\n"
 			"  -g, --graph          generate output for graphviz's dot\n"
 			"  -h, --help           display this help message\n"
 			"  -l, --linear         enable linear output\n"
+			"  -o, --optdeps        list packages that are optionally depended upon by the named package\n"
 			"  -r, --reverse        list packages that depend on the named package\n"
 			"  -s, --sync           search sync databases instead of local\n"
 			"  -u, --unique         show dependencies with no duplicates (implies -l)\n"
 			"  -v, --version        display the version\n"
@@ -276,8 +278,9 @@  static int parse_options(int argc, char *argv[])
 		{"depth",   required_argument,    0, 'd'},
 		{"graph",   no_argument,          0, 'g'},
 		{"help",    no_argument,          0, 'h'},
 		{"linear",  no_argument,          0, 'l'},
+		{"optdeps", no_argument,          0, 'o'},
 		{"reverse", no_argument,          0, 'r'},
 		{"sync",    no_argument,          0, 's'},
 		{"unique",  no_argument,          0, 'u'},
 		{"version", no_argument,          0, 'v'},
@@ -293,9 +296,9 @@  static int parse_options(int argc, char *argv[])
 	if(strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
 		style = &graph_utf8;
 	}
 
-	while((opt = getopt_long(argc, argv, "ab:cd:ghlrsuv", opts, &option_index))) {
+	while((opt = getopt_long(argc, argv, "ab:cd:ghlorsuv", opts, &option_index))) {
 		if(opt < 0) {
 			break;
 		}
 
@@ -331,8 +334,11 @@  static int parse_options(int argc, char *argv[])
 				break;
 			case 'l':
 				style = &graph_linear;
 				break;
+			case 'o':
+				optdeps = 1;
+				break;
 			case 'r':
 				reverse = 1;
 				break;
 			case 's':
@@ -464,12 +470,23 @@  static alpm_list_t *get_pkg_deps(alpm_pkg_t *pkg)
 	}
 	return dep_strings;
 }
 
+static alpm_list_t *get_pkg_optdeps(alpm_pkg_t *pkg)
+{
+	alpm_list_t *i, *dep_strings = NULL;
+	for(i = alpm_pkg_get_optdepends(pkg); i; i = alpm_list_next(i)) {
+		alpm_depend_t *dep = i->data;
+		char *ds = alpm_dep_compute_string(dep);
+		dep_strings = alpm_list_add(dep_strings, ds);
+	}
+	return dep_strings;
+}
+
 /**
  * walk dependencies, showing dependencies of the target
  */
-static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, tdepth *depth, int rev)
+static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, tdepth *depth, int rev, int optdeps)
 {
 	alpm_list_t *deps, *i;
 
 	if(!pkg || ((max_depth >= 0) && (depth->level > max_depth))) {
@@ -482,8 +499,17 @@  static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, tdepth *depth, int r
 		deps = alpm_pkg_compute_requiredby(pkg);
 	} else {
 		deps = get_pkg_deps(pkg);
 	}
+	if(optdeps) {
+		alpm_list_t *odeps;
+		if(rev) {
+			odeps = alpm_pkg_compute_optionalfor(pkg);
+		} else {
+			odeps = get_pkg_optdeps(pkg);
+		}
+		deps = alpm_list_join(deps, odeps);
+	}
 
 	for(i = deps; i; i = alpm_list_next(i)) {
 		const char *pkgname = i->data;
 		int last = alpm_list_next(i) ? 0 : 1;
@@ -514,9 +540,9 @@  static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, tdepth *depth, int r
 					} else {
 						d.prev = NULL;
 					}
 				}
-				walk_deps(dblist, dep_pkg, &d, rev);
+				walk_deps(dblist, dep_pkg, &d, rev, optdeps);
 				depth->next = NULL;
 			}
 		}
 	}
@@ -575,9 +601,9 @@  int main(int argc, char *argv[])
 		NULL,
 		NULL,
 		1
 	};
-	walk_deps(dblist, pkg, &d, reverse);
+	walk_deps(dblist, pkg, &d, reverse, optdeps);
 
 	print_end();
 
 	if(freelist) {