[pacman-dev] [PATCH] Add --ignore-depends option

Florian Pritz bluewind at xinu.at
Sun Jul 6 10:31:22 EDT 2014


This allows to ignore specific dependencies.

TODO: documentation

Signed-off-by: Florian Pritz <bluewind at xinu.at>
---

This patch is still missing documentation as noted in the commit message, but
apart from that it works (at least alpm_option_set_ignoredeps(), didn't test
_remove_).

Now that I have a POC, could I get some feedback on the idea and the
code?

 lib/libalpm/alpm.h             | 11 ++++++
 lib/libalpm/deps.c             |  8 +++-
 lib/libalpm/handle.c           | 89 ++++++++++++++++++++++++++++++++++++++++++
 lib/libalpm/handle.h           |  1 +
 src/pacman/conf.c              |  2 +
 src/pacman/conf.h              |  4 +-
 src/pacman/pacman.c            |  4 ++
 test/pacman/tests/TESTS        |  1 +
 test/pacman/tests/ignoredep.py | 20 ++++++++++
 9 files changed, 137 insertions(+), 3 deletions(-)
 create mode 100644 test/pacman/tests/ignoredep.py

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index db1e0cd..d5b2c4c 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -857,6 +857,17 @@ int alpm_option_set_ignoregroups(alpm_handle_t *handle, alpm_list_t *ignoregrps)
 int alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *grp);
 /** @} */
 
+/** @name Accessors to the list of ignored dependencies.
+ * These functions modify the list of dependencies that
+ * should be ignored by a sysupgrade.
+ * @{
+ */
+alpm_list_t *alpm_option_get_ignoredeps(alpm_handle_t *handle);
+int alpm_option_add_ignoredep(alpm_handle_t *handle, const char *dep);
+int alpm_option_set_ignoredeps(alpm_handle_t *handle, alpm_list_t *ignoredeps);
+int alpm_option_remove_ignoredep(alpm_handle_t *handle, const char *dep);
+/** @} */
+
 /** Returns the targeted architecture. */
 const char *alpm_option_get_arch(alpm_handle_t *handle);
 /** Sets the targeted architecture. */
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index 1cbbc5f..6185542 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -338,8 +338,10 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle,
 			}
 			/* 1. we check the upgrade list */
 			/* 2. we check database for untouched satisfying packages */
+			/* 3. we check the dependency ignore list */
 			if(!find_dep_satisfier(upgrade, depend) &&
-					!find_dep_satisfier(dblist, depend)) {
+					!find_dep_satisfier(dblist, depend) &&
+					!find_dep_satisfier(handle->ignoredep, depend)) {
 				/* Unsatisfied dependency in the upgrade list */
 				alpm_depmissing_t *miss;
 				char *missdepstring = alpm_dep_compute_string(depend);
@@ -368,9 +370,11 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle,
 				/* we won't break this depend, if it is already broken, we ignore it */
 				/* 1. check upgrade list for satisfiers */
 				/* 2. check dblist for satisfiers */
+				/* 3. we check the dependency ignore list */
 				if(causingpkg &&
 						!find_dep_satisfier(upgrade, depend) &&
-						!find_dep_satisfier(dblist, depend)) {
+						!find_dep_satisfier(dblist, depend) &&
+						!find_dep_satisfier(handle->ignoredep, depend)) {
 					alpm_depmissing_t *miss;
 					char *missdepstring = alpm_dep_compute_string(depend);
 					_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n",
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 0842d51..cb378cc 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -86,6 +86,10 @@ void _alpm_handle_free(alpm_handle_t *handle)
 	FREELIST(handle->noextract);
 	FREELIST(handle->ignorepkg);
 	FREELIST(handle->ignoregroup);
+
+	alpm_list_free_inner(handle->ignoredep, (alpm_list_fn_free)_alpm_pkg_free);
+	alpm_list_free(handle->ignoredep);
+
 	FREE(handle);
 }
 
@@ -234,6 +238,12 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle)
 	return handle->ignoregroup;
 }
 
+alpm_list_t SYMEXPORT *alpm_option_get_ignoredeps(alpm_handle_t *handle)
+{
+	CHECK_HANDLE(handle, return NULL);
+	return handle->ignoredep;
+}
+
 const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle)
 {
 	CHECK_HANDLE(handle, return NULL);
@@ -552,6 +562,85 @@ int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char *
 	return 0;
 }
 
+static alpm_pkg_t* parse_ignoredep(const char *dep)
+{
+	char *entry = strdup(dep);
+	char *save, *token;
+
+	alpm_pkg_t *pkg = _alpm_pkg_new();
+	pkg->ops = &default_pkg_ops;
+
+	pkg->name = strdup(strtok_r(entry, "=", &save));
+	pkg->name_hash = _alpm_hash_sdbm(pkg->name);
+
+	token = strtok_r(save, "=", &save);
+	if (token) {
+		pkg->version = strdup(token);
+	} else {
+		_alpm_pkg_free(pkg);
+		pkg = NULL;
+	}
+
+	free(entry);
+	return pkg;
+}
+
+int SYMEXPORT alpm_option_add_ignoredep(alpm_handle_t *handle, const char *dep)
+{
+	CHECK_HANDLE(handle, return -1);
+
+	alpm_pkg_t *pkg = parse_ignoredep(dep);
+	if (!pkg) {
+		_alpm_log(handle, ALPM_LOG_WARNING, "Invalid format for dependency ignore entry. Skipping '%s'\n", dep);
+		return 1;
+	}
+
+	pkg->handle = handle;
+	handle->ignoredep = alpm_list_add(handle->ignoredep, pkg);
+	return 0;
+}
+
+int SYMEXPORT alpm_option_set_ignoredeps(alpm_handle_t *handle, alpm_list_t *ignoredeps)
+{
+	CHECK_HANDLE(handle, return -1);
+	if(handle->ignoredep) {
+		alpm_list_free_inner(handle->ignoredep, (alpm_list_fn_free)_alpm_pkg_free);
+		alpm_list_free(handle->ignoredep);
+	}
+	for (alpm_list_t *i = ignoredeps; i; i = i->next) {
+		alpm_option_add_ignoredep(handle, i->data);
+	 }
+	return 0;
+}
+
+static int ignoredep_cmp(const void *data, const void *dep)
+{
+	alpm_pkg_t *pkg1 = ((alpm_list_t*)data)->data;
+	alpm_pkg_t *pkg2 = parse_ignoredep(dep);
+
+	if (!pkg2) {
+		return -1;
+	}
+
+	if (pkg1->name == pkg2->name && pkg1->version == pkg2->version) {
+		return 0;
+	}
+
+	return -1;
+}
+
+int SYMEXPORT alpm_option_remove_ignoredep(alpm_handle_t *handle, const char *dep)
+{
+	alpm_pkg_t *vdata = NULL;
+	CHECK_HANDLE(handle, return -1);
+	handle->ignoredep = alpm_list_remove(handle->ignoredep, dep, &ignoredep_cmp, (void **)&vdata);
+	if(vdata != NULL) {
+		alpm_pkg_free(vdata);
+		return 1;
+	}
+	return 0;
+}
+
 int SYMEXPORT alpm_option_set_arch(alpm_handle_t *handle, const char *arch)
 {
 	CHECK_HANDLE(handle, return -1);
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 85c64f6..f164e1c 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -83,6 +83,7 @@ struct __alpm_handle_t {
 	alpm_list_t *noextract;   /* List of files NOT to extract */
 	alpm_list_t *ignorepkg;   /* List of packages to ignore */
 	alpm_list_t *ignoregroup; /* List of groups to ignore */
+	alpm_list_t *ignoredep;   /* List of packages to ignore dependencies on */
 
 	/* options */
 	char *arch;              /* Architecture of packages we should allow */
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 0e483f7..0d7a605 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -134,6 +134,7 @@ int config_free(config_t *oldconfig)
 	FREELIST(oldconfig->holdpkg);
 	FREELIST(oldconfig->ignorepkg);
 	FREELIST(oldconfig->ignoregrp);
+	FREELIST(oldconfig->ignoredep);
 	FREELIST(oldconfig->noupgrade);
 	FREELIST(oldconfig->noextract);
 	free(oldconfig->configfile);
@@ -738,6 +739,7 @@ static int setup_libalpm(void)
 
 	alpm_option_set_ignorepkgs(handle, config->ignorepkg);
 	alpm_option_set_ignoregroups(handle, config->ignoregrp);
+	alpm_option_set_ignoredeps(handle, config->ignoredep);
 	alpm_option_set_noupgrades(handle, config->noupgrade);
 	alpm_option_set_noextracts(handle, config->noextract);
 
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index e8cac50..0e5c86f 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -101,6 +101,7 @@ typedef struct __config_t {
 	alpm_list_t *holdpkg;
 	alpm_list_t *ignorepkg;
 	alpm_list_t *ignoregrp;
+	alpm_list_t *ignoredep;
 	alpm_list_t *noupgrade;
 	alpm_list_t *noextract;
 	char *xfercommand;
@@ -176,7 +177,8 @@ enum {
 	OP_UNNEEDED,
 	OP_VERBOSE,
 	OP_DOWNLOADONLY,
-	OP_REFRESH
+	OP_REFRESH,
+	OP_IGNOREDEP
 };
 
 /* clean method */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index e8c5f9e..3837df4 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -704,6 +704,9 @@ static int parsearg_upgrade(int opt)
 		case OP_IGNOREGROUP:
 			parsearg_util_addlist(&(config->ignoregrp));
 			break;
+		case OP_IGNOREDEP:
+			parsearg_util_addlist(&(config->ignoredep));
+			break;
 		default: return 1;
 	}
 	return 0;
@@ -852,6 +855,7 @@ static int parseargs(int argc, char *argv[])
 		{"noconfirm",  no_argument,       0, OP_NOCONFIRM},
 		{"config",     required_argument, 0, OP_CONFIG},
 		{"ignore",     required_argument, 0, OP_IGNORE},
+		{"ignore-depends",     required_argument, 0, OP_IGNOREDEP},
 		{"debug",      optional_argument, 0, OP_DEBUG},
 		{"force",      no_argument,       0, OP_FORCE},
 		{"noprogressbar", no_argument,    0, OP_NOPROGRESSBAR},
diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS
index dc47294..8528000 100644
--- a/test/pacman/tests/TESTS
+++ b/test/pacman/tests/TESTS
@@ -57,6 +57,7 @@ TESTS += test/pacman/tests/ignore005.py
 TESTS += test/pacman/tests/ignore006.py
 TESTS += test/pacman/tests/ignore007.py
 TESTS += test/pacman/tests/ignore008.py
+TESTS += test/pacman/tests/ignoredep.py
 TESTS += test/pacman/tests/ldconfig001.py
 TESTS += test/pacman/tests/ldconfig002.py
 TESTS += test/pacman/tests/ldconfig003.py
diff --git a/test/pacman/tests/ignoredep.py b/test/pacman/tests/ignoredep.py
new file mode 100644
index 0000000..d66ec09
--- /dev/null
+++ b/test/pacman/tests/ignoredep.py
@@ -0,0 +1,20 @@
+self.description = "Update a package using --ignore-depends"
+
+lp1 = pmpkg("pkg1", "1.0-1")
+
+lp2 = pmpkg("pkg2", "1.0-1")
+lp2.depends = ["pkg1=1.0"]
+
+sp1 = pmpkg("pkg1", "2.0-1")
+
+for p in lp1, lp2:
+	self.addpkg2db("local", p);
+
+self.addpkg2db("sync", sp1);
+
+self.args = "-Su --ignore-depends pkg1=1.0"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PKG_VERSION=pkg1|2.0-1")
+self.addrule("PKG_EXIST=pkg2")
+self.addrule("PKG_EXIST=pkg1")
-- 
2.0.0


More information about the pacman-dev mailing list