diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 1ae7ab1d..c3ea3169 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -22,6 +22,7 @@
* along with this program. If not, see .
*/
+#include
#include
#include
#include
@@ -161,7 +162,7 @@ static void remove_prepare_keep_needed(alpm_handle_t *handle, alpm_list_t *lp)
* @param handle the context handle
* @param lp list of packages to be removed
*/
-static void remove_notify_needed_optdepends(alpm_handle_t *handle, alpm_list_t *lp)
+static void remove_notify_needed_optdepends(alpm_handle_t *handle, alpm_list_t *lp, int remove_optdepends)
{
alpm_list_t *i;
@@ -169,21 +170,29 @@ static void remove_notify_needed_optdepends(alpm_handle_t *handle, alpm_list_t *
alpm_pkg_t *pkg = i->data;
alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg);
- if(optdeps && !alpm_pkg_find(lp, pkg->name)) {
- alpm_list_t *j;
- for(j = optdeps; j; j = alpm_list_next(j)) {
- alpm_depend_t *optdep = j->data;
- char *optstring = alpm_dep_compute_string(optdep);
- if(alpm_find_satisfier(lp, optstring)) {
+ if (!optdeps || alpm_pkg_find(lp, pkg->name)) {
+ continue;
+ }
+
+ alpm_list_t *j;
+ for(j = optdeps; j; j = alpm_list_next(j)) {
+ alpm_depend_t *optdep = j->data;
+ char *optstring = alpm_dep_compute_string(optdep);
+ if(alpm_find_satisfier(lp, optstring)) {
+ if (remove_optdepends) {
+ // -Rss, we delete optdepends
alpm_event_optdep_removal_t event = {
.type = ALPM_EVENT_OPTDEP_REMOVAL,
.pkg = pkg,
.optdep = optdep
};
EVENT(handle, &event);
+ } else {
+ // -Rs, we keep optdepends
+ alpm_list_remove(lp, optdep, _alpm_pkg_dep_cmp, NULL);
}
- free(optstring);
}
+ free(optstring);
}
}
}
@@ -257,7 +266,7 @@ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
/* Note packages being removed that are optdepends for installed packages */
if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {
- remove_notify_needed_optdepends(handle, trans->remove);
+ remove_notify_needed_optdepends(handle, trans->remove, (trans->flags & ALPM_TRANS_FLAG_RECURSEALL));
}
if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 7877b17a..f89b0001 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -835,6 +835,19 @@ int _alpm_ldconfig(alpm_handle_t *handle)
return 0;
}
+/** Helper function for comparing names of a dependency and a package
+ * @param p1 void pointer of the package
+ * @param p2 void pointer of the dependency
+ * @return result of the comparison of the names
+ * */
+int _alpm_pkg_dep_cmp(const void *p1, const void *p2)
+{
+ alpm_pkg_t *pkg = (alpm_pkg_t *) p1;
+ alpm_depend_t *dep = (alpm_depend_t *) p2;
+
+ return _alpm_str_cmp(pkg->name, dep->name);
+}
+
/** Helper function for comparing strings using the alpm "compare func"
* signature.
* @param s1 first string to be compared
diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h
index 5090c545..9af97c89 100644
--- a/lib/libalpm/util.h
+++ b/lib/libalpm/util.h
@@ -160,6 +160,8 @@ void *_alpm_realloc(void **data, size_t *current, const size_t required);
void *_alpm_greedy_grow(void **data, size_t *current, const size_t required);
alpm_errno_t _alpm_read_file(const char *filepath, unsigned char **data, size_t *data_len);
+int _alpm_pkg_dep_cmp(const void *p1, const void *p2);
+
#ifndef HAVE_STRSEP
char *strsep(char **, const char *);
#endif
diff --git a/test/pacman/meson.build b/test/pacman/meson.build
index 4a73b600..3de04cd0 100644
--- a/test/pacman/meson.build
+++ b/test/pacman/meson.build
@@ -126,6 +126,7 @@ pacman_tests = [
'tests/reason001.py',
'tests/remove-assumeinstalled.py',
'tests/remove-directory-replaced-with-symlink.py',
+ 'tests/remove-keep-optdepend-of-installed-package.py',
'tests/remove-optdepend-of-installed-package.py',
'tests/remove-print-empty-replacements.py',
'tests/remove-recursive-cycle.py',
diff --git a/test/pacman/tests/remove-keep-optdepend-of-installed-package.py b/test/pacman/tests/remove-keep-optdepend-of-installed-package.py
new file mode 100644
index 00000000..103e4802
--- /dev/null
+++ b/test/pacman/tests/remove-keep-optdepend-of-installed-package.py
@@ -0,0 +1,21 @@
+self.description = "Do not remove packages which is an optdepend of another package"
+
+p1 = pmpkg("a")
+p1.depends = ["b"]
+self.addpkg2db("local", p1)
+
+p2 = pmpkg("b")
+self.addpkg2db("local", p2)
+
+
+p3 = pmpkg("c")
+p3.optdepends = ["b: for foobar"]
+self.addpkg2db("local", p3)
+
+self.args = "-Rs %s" % p1.name
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("!PKG_EXIST=%s" % p1.name)
+self.addrule("PKG_EXIST=%s" % p2.name)
+self.addrule("PKG_EXIST=%s" % p3.name)
+self.addrule("!PACMAN_OUTPUT=%s optionally requires %s" % (p3.name, p2.name))
diff --git a/test/pacman/tests/remove-optdepend-of-installed-package.py b/test/pacman/tests/remove-optdepend-of-installed-package.py
index 4973df5f..10cbae3b 100644
--- a/test/pacman/tests/remove-optdepend-of-installed-package.py
+++ b/test/pacman/tests/remove-optdepend-of-installed-package.py
@@ -1,15 +1,21 @@
self.description = "Remove packages which is an optdepend of another package"
-p1 = pmpkg("dep")
+p1 = pmpkg("a")
+p1.depends = ["b"]
self.addpkg2db("local", p1)
-p2 = pmpkg("pkg")
-p2.optdepends = ["dep: for foobar"]
+p2 = pmpkg("b")
self.addpkg2db("local", p2)
-self.args = "-R %s" % p1.name
+
+p3 = pmpkg("c")
+p3.optdepends = ["b: for foobar"]
+self.addpkg2db("local", p3)
+
+self.args = "-Rss %s" % p1.name
self.addrule("PACMAN_RETCODE=0")
self.addrule("!PKG_EXIST=%s" % p1.name)
-self.addrule("PKG_EXIST=%s" % p2.name)
-self.addrule("PACMAN_OUTPUT=%s optionally requires %s" % (p2.name, p1.name))
+self.addrule("!PKG_EXIST=%s" % p2.name)
+self.addrule("PKG_EXIST=%s" % p3.name)
+self.addrule("PACMAN_OUTPUT=%s optionally requires %s" % (p3.name, p2.name))