[pacman-dev] [RFC] [IDEA] Possibility to ignore specific dependencies
Hi, I'm thinking about having perl packages depend on a more specific perl version (like a provided perl-5.20 instead of simply perl), but that brings the same issues we currently have with kernel modules. Everything that's not in the repos will prevent a clean upgrade because it depends on the old package. One idea to get around this would be to add an option like --ignore-dependency perl-5.18 which means that something like -Syu (or -S, -U and similar) will error when there are dependencies for perl-5.20, but will not error when there are packages installed that depend on perl-5.18. Side note: Not yet sure how the final syntax will look like, that - as a separator seems like a bad choice because it's ambiguous (where does the pkgname end if there doesn't have to be a pkgver?) This is a more controlled form of -d if you will. Optionally I'd also want this to work like -dd if used as "--ignore-dependency perl" which means that all perl dependencies will be ignored, but dependencies on other packages will not. Obviously this will not only be useful for perl, but also for linux modules, though I don't have any of those installed from AUR so I don't know if people for other workarounds. This is only an idea for now, depending on feedback I'd look into implementing it.
This allows to ignore specific dependencies. TODO: documentation Signed-off-by: Florian Pritz <bluewind@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
On 22/06/14 23:32, Florian Pritz wrote:
Hi,
I'm thinking about having perl packages depend on a more specific perl version (like a provided perl-5.20 instead of simply perl), but that brings the same issues we currently have with kernel modules. Everything that's not in the repos will prevent a clean upgrade because it depends on the old package.
One idea to get around this would be to add an option like --ignore-dependency perl-5.18 which means that something like -Syu (or -S, -U and similar) will error when there are dependencies for perl-5.20, but will not error when there are packages installed that depend on perl-5.18.
Side note: Not yet sure how the final syntax will look like, that - as a separator seems like a bad choice because it's ambiguous (where does the pkgname end if there doesn't have to be a pkgver?)
This is a more controlled form of -d if you will. Optionally I'd also want this to work like -dd if used as "--ignore-dependency perl" which means that all perl dependencies will be ignored, but dependencies on other packages will not.
Obviously this will not only be useful for perl, but also for linux modules, though I don't have any of those installed from AUR so I don't know if people for other workarounds.
This is only an idea for now, depending on feedback I'd look into implementing it.
So this is the process now: pacman -Syu <- perl version dependency error pacman -Sd perl pacman -Su and this will change to: pacman -Syu <- perl version dependency error pacman -Su --ignore-depends perl=5.18 Is that correct? Allan
On 13.07.2014 09:27, Allan McRae wrote:
On 22/06/14 23:32, Florian Pritz wrote: So this is the process now:
pacman -Syu <- perl version dependency error pacman -Sd perl pacman -Su
and this will change to:
pacman -Syu <- perl version dependency error pacman -Su --ignore-depends perl=5.18
Is that correct?
Correct with the difference that -Sd perl will ignore the versions for all dependencies of perl and those of packages that get pulled in by a (new) dependency. --ignore-depends simply makes pacman believe that perl=5.18 is "installed" so dependency checks for other packages run just the way they normally would. Far smaller scope, more obvious what will happen and probably enough to deal with most cases without having to risk fallout by ignoring too much.
v2: - Use _alpm_splitdep rather than implementing it myself (thanks to Andrew for the idea) I'd love feedback on the idea/implementation (preferably from Allan) and also general feedback on this try at documenting it (in man pacman):
--ignore-depends provider=version,...
Make pacman believe the package named provider with version version is installed when doing dependency checks. This allows to disable certain dependency checks without affecting everything the way the --nodeps option does.
This allows to reuse the provision checker for a simple list of provisions without a package. Signed-off-by: Florian Pritz <bluewind@xinu.at> --- lib/libalpm/deps.c | 27 +++++++++++++++++++-------- lib/libalpm/deps.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 1cbbc5f..5c76da7 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -421,17 +421,17 @@ int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep) return dep_vercmp(pkg->version, dep->mod, dep->version); } -int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +/** + * @param dep dependency to check agains the provision list + * @param provisions provision list + * @return 1 if provider is found, 0 otherwise + */ +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions) { - alpm_list_t *i; - int satisfy = _alpm_depcmp_literal(pkg, dep); - - if(satisfy) { - return satisfy; - } + int satisfy = 0; /* check provisions, name and version if available */ - for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) { + for(alpm_list_t *i = provisions; i && !satisfy; i = i->next) { alpm_depend_t *provision = i->data; if(dep->mod == ALPM_DEP_MOD_ANY) { @@ -449,6 +449,17 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return satisfy; } +int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +{ + int satisfy = _alpm_depcmp_literal(pkg, dep); + + if(satisfy) { + return satisfy; + } + + return _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); +} + alpm_depend_t *_alpm_splitdep(const char *depstring) { alpm_depend_t *depend; diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index e36bbb3..f4eadba 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -37,6 +37,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t alpm_list_t **data); alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); #endif /* _ALPM_DEPS_H */ -- 2.0.4
This allows to ignore specific dependencies. TODO: documentation Signed-off-by: Florian Pritz <bluewind@xinu.at> --- lib/libalpm/alpm.h | 11 ++++++++ lib/libalpm/deps.c | 8 ++++-- lib/libalpm/handle.c | 62 ++++++++++++++++++++++++++++++++++++++++++ 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, 110 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 5c76da7..44f9ebc 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) && + !_alpm_depcmp_provides(depend, handle->ignoredep)) { /* 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) && + !_alpm_depcmp_provides(depend, handle->ignoredep)) { 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..e90a6b7 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -37,6 +37,7 @@ #include "delta.h" #include "trans.h" #include "alpm.h" +#include "deps.h" alpm_handle_t *_alpm_handle_new(void) { @@ -86,6 +87,7 @@ void _alpm_handle_free(alpm_handle_t *handle) FREELIST(handle->noextract); FREELIST(handle->ignorepkg); FREELIST(handle->ignoregroup); + FREELIST(handle->ignoredep); FREE(handle); } @@ -234,6 +236,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 +560,60 @@ int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char * return 0; } +int SYMEXPORT alpm_option_add_ignoredep(alpm_handle_t *handle, const char *dep) +{ + CHECK_HANDLE(handle, return -1); + + alpm_depend_t *provider = _alpm_splitdep(dep); + if (!provider) { + _alpm_log(handle, ALPM_LOG_WARNING, "Invalid format for dependency ignore entry. Skipping '%s'\n", dep); + return 1; + } + + handle->ignoredep = alpm_list_add(handle->ignoredep, provider); + 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(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_depend_t *dep1 = ((alpm_list_t*)data)->data; + alpm_depend_t *dep2 = _alpm_splitdep(dep); + + if (!dep2) { + return -1; + } + + if (strcmp(dep1->name, dep2->name) && strcmp(dep1->version, dep2->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 12a4f7a..95dbe6f 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -707,6 +707,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; @@ -855,6 +858,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 1b5a81f..59b46ce 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.4
On 08/06/14 at 09:55pm, Florian Pritz wrote:
This allows to ignore specific dependencies.
TODO: documentation
Signed-off-by: Florian Pritz <bluewind@xinu.at> --- lib/libalpm/alpm.h | 11 ++++++++ lib/libalpm/deps.c | 8 ++++-- lib/libalpm/handle.c | 62 ++++++++++++++++++++++++++++++++++++++++++ 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, 110 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 5c76da7..44f9ebc 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) && + !_alpm_depcmp_provides(depend, handle->ignoredep)) { /* 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) && + !_alpm_depcmp_provides(depend, handle->ignoredep)) { 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..e90a6b7 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -37,6 +37,7 @@ #include "delta.h" #include "trans.h" #include "alpm.h" +#include "deps.h"
alpm_handle_t *_alpm_handle_new(void) { @@ -86,6 +87,7 @@ void _alpm_handle_free(alpm_handle_t *handle) FREELIST(handle->noextract); FREELIST(handle->ignorepkg); FREELIST(handle->ignoregroup); + FREELIST(handle->ignoredep);
You need to use alpm_list_free_inner with _alpm_dep_free and alpm_list_free, not FREELIST.
FREE(handle); }
@@ -234,6 +236,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; +} +
Using strings with add/set/remove but returning depend_t from get_ignoredepends is confusing. Can we make them consistent?
const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) { CHECK_HANDLE(handle, return NULL); @@ -552,6 +560,60 @@ int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char * return 0; }
+int SYMEXPORT alpm_option_add_ignoredep(alpm_handle_t *handle, const char *dep) +{ + CHECK_HANDLE(handle, return -1); + + alpm_depend_t *provider = _alpm_splitdep(dep); + if (!provider) { + _alpm_log(handle, ALPM_LOG_WARNING, "Invalid format for dependency ignore entry. Skipping '%s'\n", dep); + return 1; + } + + handle->ignoredep = alpm_list_add(handle->ignoredep, provider); + 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(handle->ignoredep); + } + for (alpm_list_t *i = ignoredeps; i; i = i->next) { + alpm_option_add_ignoredep(handle, i->data);
This should check for failure and abort like set_cachedirs.
+ } + return 0; +} + +static int ignoredep_cmp(const void *data, const void *dep) +{ + alpm_depend_t *dep1 = ((alpm_list_t*)data)->data; + alpm_depend_t *dep2 = _alpm_splitdep(dep);
Do the splitdep in remove_ignoredep so it only has to be done once. The resulting depend_t also needs to be free'd.
+ + if (!dep2) { + return -1; + } + + if (strcmp(dep1->name, dep2->name) && strcmp(dep1->version, dep2->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);
vdata needs to be a depend_t, not a package.
+ 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 12a4f7a..95dbe6f 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -707,6 +707,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;
Why is this limited to -S and -U? -dd applies to all transactions.
default: return 1; } return 0; @@ -855,6 +858,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 1b5a81f..59b46ce 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.4
On Wed, Aug 6, 2014 at 3:55 PM, Florian Pritz <bluewind@xinu.at> wrote:
v2: - Use _alpm_splitdep rather than implementing it myself (thanks to Andrew for the idea)
I'd love feedback on the idea/implementation (preferably from Allan) and also general feedback on this try at documenting it (in man pacman):
--ignore-depends provider=version,...
Make pacman believe the package named provider with version version is installed when doing dependency checks. This allows to disable certain dependency checks without affecting everything the way the --nodeps option does.
It's my preference to put double quotes around example names found in prose (e.g. the package named "provider" with version "version"). Also, I think some users may get confused about the use of the word "provider" instead of using the word "package", but maybe I'm underestimating users. Finally, I think a slight reword of the last sentence would be beneficial. For example: "This allows one to disable specific dependency checks without affecting all dependency checks, which the --nodeps option does." or "This allows one to disable specific dependency checks without affecting all dependency checks. To disable all dependency checking, see the --nodeps option." I prefer the latter simply because it is explicitly clear, but it is more verbose, which could be seen as a bad thing. Hope this helps. Jason
On 07/08/14 05:55, Florian Pritz wrote:
v2: - Use _alpm_splitdep rather than implementing it myself (thanks to Andrew for the idea)
I'd love feedback on the idea/implementation (preferably from Allan) and also general feedback on this try at documenting it (in man pacman):
Jason has the man page covered. I have not looked at the patch in detail. Given Andrew took at least a quick pass, I assume it is mostly OK. This does not stand out to me as a must have option (we can get very close to this with -d and -dd), given this is going to be used to get around dependency issues in system updates. However, I see some utility. So I have to way up the small utility versus the added complexity. I'll definitely make a decision in the next couple of weeks, before we freeze. I anyone else going to speak out in favour/against this option? Andrew + Dave + Dan? A
v3: - Change the option name to --assume-installed - Add manpage - Make the API consistent by passing around alpm_depend_t only, no char* - returning a char* list in *_get_* would require either saving it (bad) or creating it on request which would require the user to free it (bad because different from all other *_get_* functions. - This means exporting alpm_dep_free and alpm_splitdep - *_set_* now aborts on errors - splitdep moved to pacman.c due to API change - Now works for -R - Testcase for -R and for -S --assume-installed with just a package name Thanks to Andrew and Jason. This changeset is available at <https://git.server-speed.net/users/flo/pacman/log/?h=working-assume-installed-v2>.
This allows to reuse the provision checker for a simple list of provisions without a package. Signed-off-by: Florian Pritz <bluewind@xinu.at> --- v3: no changes here lib/libalpm/deps.c | 27 +++++++++++++++++++-------- lib/libalpm/deps.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index c5acfc9..920753b 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -416,17 +416,17 @@ int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep) return dep_vercmp(pkg->version, dep->mod, dep->version); } -int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +/** + * @param dep dependency to check agains the provision list + * @param provisions provision list + * @return 1 if provider is found, 0 otherwise + */ +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions) { - alpm_list_t *i; - int satisfy = _alpm_depcmp_literal(pkg, dep); - - if(satisfy) { - return satisfy; - } + int satisfy = 0; /* check provisions, name and version if available */ - for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) { + for(alpm_list_t *i = provisions; i && !satisfy; i = i->next) { alpm_depend_t *provision = i->data; if(dep->mod == ALPM_DEP_MOD_ANY) { @@ -444,6 +444,17 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return satisfy; } +int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +{ + int satisfy = _alpm_depcmp_literal(pkg, dep); + + if(satisfy) { + return satisfy; + } + + return _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); +} + alpm_depend_t *_alpm_splitdep(const char *depstring) { alpm_depend_t *depend; diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index e36bbb3..f4eadba 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -37,6 +37,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t alpm_list_t **data); alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); #endif /* _ALPM_DEPS_H */ -- 2.1.0
On 09/17/14 at 01:02am, Florian Pritz wrote:
This allows to reuse the provision checker for a simple list of provisions without a package.
Signed-off-by: Florian Pritz <bluewind@xinu.at> ---
v3: no changes here
lib/libalpm/deps.c | 27 +++++++++++++++++++-------- lib/libalpm/deps.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index c5acfc9..920753b 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -416,17 +416,17 @@ int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep) return dep_vercmp(pkg->version, dep->mod, dep->version); }
-int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +/** + * @param dep dependency to check agains the provision list + * @param provisions provision list + * @return 1 if provider is found, 0 otherwise + */ +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions) { - alpm_list_t *i; - int satisfy = _alpm_depcmp_literal(pkg, dep); - - if(satisfy) { - return satisfy; - } + int satisfy = 0;
/* check provisions, name and version if available */ - for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) { + for(alpm_list_t *i = provisions; i && !satisfy; i = i->next) {
i should be declared at the top of the block.
alpm_depend_t *provision = i->data;
if(dep->mod == ALPM_DEP_MOD_ANY) { @@ -444,6 +444,17 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return satisfy; }
+int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +{ + int satisfy = _alpm_depcmp_literal(pkg, dep); + + if(satisfy) { + return satisfy; + } + + return _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); +}
This returns a boolean, is there any reason to keep around satisfy instead of simplifying this to: return _alpm_depcmp_literal(...) || _alpm_depcmp_provides(...)
+ alpm_depend_t *_alpm_splitdep(const char *depstring) { alpm_depend_t *depend; diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index e36bbb3..f4eadba 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -37,6 +37,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t alpm_list_t **data); alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep);
#endif /* _ALPM_DEPS_H */ -- 2.1.0
This allows to reuse the provision checker for a simple list of provisions without a package. Signed-off-by: Florian Pritz <bluewind@xinu.at> --- v4: - Incorporate suggestions from Andrew lib/libalpm/deps.c | 21 ++++++++++++++------- lib/libalpm/deps.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index c5acfc9..7daa28d 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -416,17 +416,18 @@ int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep) return dep_vercmp(pkg->version, dep->mod, dep->version); } -int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +/** + * @param dep dependency to check agains the provision list + * @param provisions provision list + * @return 1 if provider is found, 0 otherwise + */ +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions) { + int satisfy = 0; alpm_list_t *i; - int satisfy = _alpm_depcmp_literal(pkg, dep); - - if(satisfy) { - return satisfy; - } /* check provisions, name and version if available */ - for(i = alpm_pkg_get_provides(pkg); i && !satisfy; i = i->next) { + for(i = provisions; i && !satisfy; i = i->next) { alpm_depend_t *provision = i->data; if(dep->mod == ALPM_DEP_MOD_ANY) { @@ -444,6 +445,12 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return satisfy; } +int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) +{ + return _alpm_depcmp_literal(pkg, dep) + || _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); +} + alpm_depend_t *_alpm_splitdep(const char *depstring) { alpm_depend_t *depend; diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index e36bbb3..f4eadba 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -37,6 +37,7 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t alpm_list_t **data); alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); +int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); #endif /* _ALPM_DEPS_H */ -- 2.1.0
Signed-off-by: Florian Pritz <bluewind@xinu.at> --- I'm not sure where in alpm.g the functions should be, open to suggestions. lib/libalpm/alpm.h | 2 ++ lib/libalpm/be_local.c | 2 +- lib/libalpm/be_package.c | 10 +++++----- lib/libalpm/be_sync.c | 2 +- lib/libalpm/deps.c | 14 +++++++------- lib/libalpm/deps.h | 2 -- lib/libalpm/package.c | 2 +- lib/libalpm/sync.c | 12 ++++++------ 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 29a2dda..12769a4 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1554,6 +1554,8 @@ enum alpm_caps alpm_capabilities(void); void alpm_fileconflict_free(alpm_fileconflict_t *conflict); void alpm_depmissing_free(alpm_depmissing_t *miss); void alpm_conflict_free(alpm_conflict_t *conflict); +alpm_depend_t *alpm_splitdep(const char *depstring); +void alpm_dep_free(alpm_depend_t *dep); /* End of alpm_api */ /** @} */ diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 9a9bdef..731ecf6 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -597,7 +597,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, if(!feof(fp)) goto error; else break; \ } \ if(_alpm_strip_newline(line, 0) == 0) break; \ - f = alpm_list_add(f, _alpm_splitdep(line)); \ + f = alpm_list_add(f, alpm_splitdep(line)); \ } while(1) /* note the while(1) and not (0) */ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 6ec8888..9f0134a 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -216,23 +216,23 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * /* size in the raw package is uncompressed (installed) size */ newpkg->isize = _alpm_strtoofft(ptr); } else if(strcmp(key, "depend") == 0) { - alpm_depend_t *dep = _alpm_splitdep(ptr); + alpm_depend_t *dep = alpm_splitdep(ptr); newpkg->depends = alpm_list_add(newpkg->depends, dep); } else if(strcmp(key, "optdepend") == 0) { - alpm_depend_t *optdep = _alpm_splitdep(ptr); + alpm_depend_t *optdep = alpm_splitdep(ptr); newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep); } else if(strcmp(key, "makedepend") == 0) { /* not used atm */ } else if(strcmp(key, "checkdepend") == 0) { /* not used atm */ } else if(strcmp(key, "conflict") == 0) { - alpm_depend_t *conflict = _alpm_splitdep(ptr); + alpm_depend_t *conflict = alpm_splitdep(ptr); newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); } else if(strcmp(key, "replaces") == 0) { - alpm_depend_t *replace = _alpm_splitdep(ptr); + alpm_depend_t *replace = alpm_splitdep(ptr); newpkg->replaces = alpm_list_add(newpkg->replaces, replace); } else if(strcmp(key, "provides") == 0) { - alpm_depend_t *provide = _alpm_splitdep(ptr); + alpm_depend_t *provide = alpm_splitdep(ptr); newpkg->provides = alpm_list_add(newpkg->provides, provide); } else if(strcmp(key, "backup") == 0) { alpm_backup_t *backup; diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 4b67f42..296dcc5 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -533,7 +533,7 @@ static int _alpm_validate_filename(alpm_db_t *db, const char *pkgname, #define READ_AND_SPLITDEP(f) do { \ if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \ - f = alpm_list_add(f, _alpm_splitdep(line)); \ + f = alpm_list_add(f, alpm_splitdep(line)); \ } while(1) /* note the while(1) and not (0) */ static int sync_db_read(alpm_db_t *db, struct archive *archive, diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 920753b..0ef5756 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -35,7 +35,7 @@ #include "handle.h" #include "trans.h" -void _alpm_dep_free(alpm_depend_t *dep) +void SYMEXPORT alpm_dep_free(alpm_depend_t *dep) { FREE(dep->name); FREE(dep->version); @@ -59,7 +59,7 @@ static alpm_depmissing_t *depmiss_new(const char *target, alpm_depend_t *dep, void SYMEXPORT alpm_depmissing_free(alpm_depmissing_t *miss) { - _alpm_dep_free(miss->depend); + alpm_dep_free(miss->depend); FREE(miss->target); FREE(miss->causingpkg); FREE(miss); @@ -279,12 +279,12 @@ static int no_dep_version(alpm_handle_t *handle) */ alpm_pkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring) { - alpm_depend_t *dep = _alpm_splitdep(depstring); + alpm_depend_t *dep = alpm_splitdep(depstring); if(!dep) { return NULL; } alpm_pkg_t *pkg = find_dep_satisfier(pkgs, dep); - _alpm_dep_free(dep); + alpm_dep_free(dep); return pkg; } @@ -455,7 +455,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); } -alpm_depend_t *_alpm_splitdep(const char *depstring) +alpm_depend_t SYMEXPORT *alpm_splitdep(const char *depstring) { alpm_depend_t *depend; const char *ptr, *version, *desc; @@ -759,10 +759,10 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle, CHECK_HANDLE(handle, return NULL); ASSERT(dbs, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL)); - dep = _alpm_splitdep(depstring); + dep = alpm_splitdep(depstring); ASSERT(dep, return NULL); pkg = resolvedep(handle, dep, dbs, NULL, 1); - _alpm_dep_free(dep); + alpm_dep_free(dep); return pkg; } diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index f4eadba..bd717bb 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -27,7 +27,6 @@ #include "package.h" #include "alpm.h" -void _alpm_dep_free(alpm_depend_t *dep); alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep); alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, alpm_list_t *targets, alpm_list_t *ignore, int reverse); @@ -35,7 +34,6 @@ int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit); int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data); -alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a69f454..e2997f6 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -630,7 +630,7 @@ cleanup: static void free_deplist(alpm_list_t *deps) { - alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_dep_free); alpm_list_free(deps); } diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 4c74a3a..545085b 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -524,8 +524,8 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) conflict->package1, conflict->package2); /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ - alpm_depend_t *dep1 = _alpm_splitdep(conflict->package1); - alpm_depend_t *dep2 = _alpm_splitdep(conflict->package2); + alpm_depend_t *dep1 = alpm_splitdep(conflict->package1); + alpm_depend_t *dep2 = alpm_splitdep(conflict->package2); if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; @@ -544,12 +544,12 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) } alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free); alpm_list_free(deps); - _alpm_dep_free(dep1); - _alpm_dep_free(dep2); + alpm_dep_free(dep1); + alpm_dep_free(dep2); goto cleanup; } - _alpm_dep_free(dep1); - _alpm_dep_free(dep2); + alpm_dep_free(dep1); + alpm_dep_free(dep2); /* Prints warning */ _alpm_log(handle, ALPM_LOG_WARNING, -- 2.1.0
On Wed, Sep 17, 2014 at 01:02:13AM +0200, Florian Pritz wrote:
Signed-off-by: Florian Pritz <bluewind@xinu.at> ---
I'm not sure where in alpm.g the functions should be, open to suggestions.
lib/libalpm/alpm.h | 2 ++ lib/libalpm/be_local.c | 2 +- lib/libalpm/be_package.c | 10 +++++----- lib/libalpm/be_sync.c | 2 +- lib/libalpm/deps.c | 14 +++++++------- lib/libalpm/deps.h | 2 -- lib/libalpm/package.c | 2 +- lib/libalpm/sync.c | 12 ++++++------ 8 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 29a2dda..12769a4 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1554,6 +1554,8 @@ enum alpm_caps alpm_capabilities(void); void alpm_fileconflict_free(alpm_fileconflict_t *conflict); void alpm_depmissing_free(alpm_depmissing_t *miss); void alpm_conflict_free(alpm_conflict_t *conflict); +alpm_depend_t *alpm_splitdep(const char *depstring);
So, this means we would then have: alpm_splitdep alpm_dep_free alpm_dep_compute_string I'd suggest exporting _alpm_splitdep as alpm_dep_new, or alpm_dep_from_depstring.
+void alpm_dep_free(alpm_depend_t *dep);
/* End of alpm_api */ /** @} */ diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 9a9bdef..731ecf6 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -597,7 +597,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, if(!feof(fp)) goto error; else break; \ } \ if(_alpm_strip_newline(line, 0) == 0) break; \ - f = alpm_list_add(f, _alpm_splitdep(line)); \ + f = alpm_list_add(f, alpm_splitdep(line)); \ } while(1) /* note the while(1) and not (0) */
static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 6ec8888..9f0134a 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -216,23 +216,23 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * /* size in the raw package is uncompressed (installed) size */ newpkg->isize = _alpm_strtoofft(ptr); } else if(strcmp(key, "depend") == 0) { - alpm_depend_t *dep = _alpm_splitdep(ptr); + alpm_depend_t *dep = alpm_splitdep(ptr); newpkg->depends = alpm_list_add(newpkg->depends, dep); } else if(strcmp(key, "optdepend") == 0) { - alpm_depend_t *optdep = _alpm_splitdep(ptr); + alpm_depend_t *optdep = alpm_splitdep(ptr); newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep); } else if(strcmp(key, "makedepend") == 0) { /* not used atm */ } else if(strcmp(key, "checkdepend") == 0) { /* not used atm */ } else if(strcmp(key, "conflict") == 0) { - alpm_depend_t *conflict = _alpm_splitdep(ptr); + alpm_depend_t *conflict = alpm_splitdep(ptr); newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); } else if(strcmp(key, "replaces") == 0) { - alpm_depend_t *replace = _alpm_splitdep(ptr); + alpm_depend_t *replace = alpm_splitdep(ptr); newpkg->replaces = alpm_list_add(newpkg->replaces, replace); } else if(strcmp(key, "provides") == 0) { - alpm_depend_t *provide = _alpm_splitdep(ptr); + alpm_depend_t *provide = alpm_splitdep(ptr); newpkg->provides = alpm_list_add(newpkg->provides, provide); } else if(strcmp(key, "backup") == 0) { alpm_backup_t *backup; diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 4b67f42..296dcc5 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -533,7 +533,7 @@ static int _alpm_validate_filename(alpm_db_t *db, const char *pkgname, #define READ_AND_SPLITDEP(f) do { \ if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \ - f = alpm_list_add(f, _alpm_splitdep(line)); \ + f = alpm_list_add(f, alpm_splitdep(line)); \ } while(1) /* note the while(1) and not (0) */
static int sync_db_read(alpm_db_t *db, struct archive *archive, diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 920753b..0ef5756 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -35,7 +35,7 @@ #include "handle.h" #include "trans.h"
-void _alpm_dep_free(alpm_depend_t *dep) +void SYMEXPORT alpm_dep_free(alpm_depend_t *dep) { FREE(dep->name); FREE(dep->version); @@ -59,7 +59,7 @@ static alpm_depmissing_t *depmiss_new(const char *target, alpm_depend_t *dep,
void SYMEXPORT alpm_depmissing_free(alpm_depmissing_t *miss) { - _alpm_dep_free(miss->depend); + alpm_dep_free(miss->depend); FREE(miss->target); FREE(miss->causingpkg); FREE(miss); @@ -279,12 +279,12 @@ static int no_dep_version(alpm_handle_t *handle) */ alpm_pkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring) { - alpm_depend_t *dep = _alpm_splitdep(depstring); + alpm_depend_t *dep = alpm_splitdep(depstring); if(!dep) { return NULL; } alpm_pkg_t *pkg = find_dep_satisfier(pkgs, dep); - _alpm_dep_free(dep); + alpm_dep_free(dep); return pkg; }
@@ -455,7 +455,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); }
-alpm_depend_t *_alpm_splitdep(const char *depstring) +alpm_depend_t SYMEXPORT *alpm_splitdep(const char *depstring) { alpm_depend_t *depend; const char *ptr, *version, *desc; @@ -759,10 +759,10 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle, CHECK_HANDLE(handle, return NULL); ASSERT(dbs, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL));
- dep = _alpm_splitdep(depstring); + dep = alpm_splitdep(depstring); ASSERT(dep, return NULL); pkg = resolvedep(handle, dep, dbs, NULL, 1); - _alpm_dep_free(dep); + alpm_dep_free(dep); return pkg; }
diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index f4eadba..bd717bb 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -27,7 +27,6 @@ #include "package.h" #include "alpm.h"
-void _alpm_dep_free(alpm_depend_t *dep); alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep); alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, alpm_list_t *targets, alpm_list_t *ignore, int reverse); @@ -35,7 +34,6 @@ int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit); int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data); -alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a69f454..e2997f6 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -630,7 +630,7 @@ cleanup:
static void free_deplist(alpm_list_t *deps) { - alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_dep_free); alpm_list_free(deps); }
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 4c74a3a..545085b 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -524,8 +524,8 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) conflict->package1, conflict->package2);
/* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ - alpm_depend_t *dep1 = _alpm_splitdep(conflict->package1); - alpm_depend_t *dep2 = _alpm_splitdep(conflict->package2); + alpm_depend_t *dep1 = alpm_splitdep(conflict->package1); + alpm_depend_t *dep2 = alpm_splitdep(conflict->package2); if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; @@ -544,12 +544,12 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) } alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free); alpm_list_free(deps); - _alpm_dep_free(dep1); - _alpm_dep_free(dep2); + alpm_dep_free(dep1); + alpm_dep_free(dep2); goto cleanup; } - _alpm_dep_free(dep1); - _alpm_dep_free(dep2); + alpm_dep_free(dep1); + alpm_dep_free(dep2);
/* Prints warning */ _alpm_log(handle, ALPM_LOG_WARNING, -- 2.1.0
Signed-off-by: Florian Pritz <bluewind@xinu.at> --- v4: - Change alpm_splitdep to alpm_dep_from_depstring - Group the functions with alpm_dep_compute_string (in alpm.h) - Add documentation to the functions (in alpm.h) lib/libalpm/alpm.h | 11 +++++++++++ lib/libalpm/be_local.c | 2 +- lib/libalpm/be_package.c | 10 +++++----- lib/libalpm/be_sync.c | 2 +- lib/libalpm/deps.c | 14 +++++++------- lib/libalpm/deps.h | 2 -- lib/libalpm/package.c | 2 +- lib/libalpm/sync.c | 12 ++++++------ 8 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 29a2dda..0eab342 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -1526,6 +1526,17 @@ alpm_list_t *alpm_checkconflicts(alpm_handle_t *handle, alpm_list_t *pkglist); */ char *alpm_dep_compute_string(const alpm_depend_t *dep); +/** Return a news allocated dependency information parsed from a string + * @param depstring a formatted string, e.g. "glibc=2.12" + * @return a dependency info structure + */ +alpm_depend_t *alpm_dep_from_depstring(const char *depstring); + +/** Free a dependency info structure + * @param dep struct to free + */ +void alpm_dep_free(alpm_depend_t *dep); + /** @} */ /** @} */ diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 9a9bdef..1543f59 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -597,7 +597,7 @@ char *_alpm_local_db_pkgpath(alpm_db_t *db, alpm_pkg_t *info, if(!feof(fp)) goto error; else break; \ } \ if(_alpm_strip_newline(line, 0) == 0) break; \ - f = alpm_list_add(f, _alpm_splitdep(line)); \ + f = alpm_list_add(f, alpm_dep_from_depstring(line)); \ } while(1) /* note the while(1) and not (0) */ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 6ec8888..3058fe3 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -216,23 +216,23 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t * /* size in the raw package is uncompressed (installed) size */ newpkg->isize = _alpm_strtoofft(ptr); } else if(strcmp(key, "depend") == 0) { - alpm_depend_t *dep = _alpm_splitdep(ptr); + alpm_depend_t *dep = alpm_dep_from_depstring(ptr); newpkg->depends = alpm_list_add(newpkg->depends, dep); } else if(strcmp(key, "optdepend") == 0) { - alpm_depend_t *optdep = _alpm_splitdep(ptr); + alpm_depend_t *optdep = alpm_dep_from_depstring(ptr); newpkg->optdepends = alpm_list_add(newpkg->optdepends, optdep); } else if(strcmp(key, "makedepend") == 0) { /* not used atm */ } else if(strcmp(key, "checkdepend") == 0) { /* not used atm */ } else if(strcmp(key, "conflict") == 0) { - alpm_depend_t *conflict = _alpm_splitdep(ptr); + alpm_depend_t *conflict = alpm_dep_from_depstring(ptr); newpkg->conflicts = alpm_list_add(newpkg->conflicts, conflict); } else if(strcmp(key, "replaces") == 0) { - alpm_depend_t *replace = _alpm_splitdep(ptr); + alpm_depend_t *replace = alpm_dep_from_depstring(ptr); newpkg->replaces = alpm_list_add(newpkg->replaces, replace); } else if(strcmp(key, "provides") == 0) { - alpm_depend_t *provide = _alpm_splitdep(ptr); + alpm_depend_t *provide = alpm_dep_from_depstring(ptr); newpkg->provides = alpm_list_add(newpkg->provides, provide); } else if(strcmp(key, "backup") == 0) { alpm_backup_t *backup; diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 4b67f42..2ee295a 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -533,7 +533,7 @@ static int _alpm_validate_filename(alpm_db_t *db, const char *pkgname, #define READ_AND_SPLITDEP(f) do { \ if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ if(_alpm_strip_newline(buf.line, buf.real_line_size) == 0) break; \ - f = alpm_list_add(f, _alpm_splitdep(line)); \ + f = alpm_list_add(f, alpm_dep_from_depstring(line)); \ } while(1) /* note the while(1) and not (0) */ static int sync_db_read(alpm_db_t *db, struct archive *archive, diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 920753b..4108aef 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -35,7 +35,7 @@ #include "handle.h" #include "trans.h" -void _alpm_dep_free(alpm_depend_t *dep) +void SYMEXPORT alpm_dep_free(alpm_depend_t *dep) { FREE(dep->name); FREE(dep->version); @@ -59,7 +59,7 @@ static alpm_depmissing_t *depmiss_new(const char *target, alpm_depend_t *dep, void SYMEXPORT alpm_depmissing_free(alpm_depmissing_t *miss) { - _alpm_dep_free(miss->depend); + alpm_dep_free(miss->depend); FREE(miss->target); FREE(miss->causingpkg); FREE(miss); @@ -279,12 +279,12 @@ static int no_dep_version(alpm_handle_t *handle) */ alpm_pkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring) { - alpm_depend_t *dep = _alpm_splitdep(depstring); + alpm_depend_t *dep = alpm_dep_from_depstring(depstring); if(!dep) { return NULL; } alpm_pkg_t *pkg = find_dep_satisfier(pkgs, dep); - _alpm_dep_free(dep); + alpm_dep_free(dep); return pkg; } @@ -455,7 +455,7 @@ int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep) return _alpm_depcmp_provides(dep, alpm_pkg_get_provides(pkg)); } -alpm_depend_t *_alpm_splitdep(const char *depstring) +alpm_depend_t SYMEXPORT *alpm_dep_from_depstring(const char *depstring) { alpm_depend_t *depend; const char *ptr, *version, *desc; @@ -759,10 +759,10 @@ alpm_pkg_t SYMEXPORT *alpm_find_dbs_satisfier(alpm_handle_t *handle, CHECK_HANDLE(handle, return NULL); ASSERT(dbs, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, NULL)); - dep = _alpm_splitdep(depstring); + dep = alpm_dep_from_depstring(depstring); ASSERT(dep, return NULL); pkg = resolvedep(handle, dep, dbs, NULL, 1); - _alpm_dep_free(dep); + alpm_dep_free(dep); return pkg; } diff --git a/lib/libalpm/deps.h b/lib/libalpm/deps.h index f4eadba..bd717bb 100644 --- a/lib/libalpm/deps.h +++ b/lib/libalpm/deps.h @@ -27,7 +27,6 @@ #include "package.h" #include "alpm.h" -void _alpm_dep_free(alpm_depend_t *dep); alpm_depend_t *_alpm_dep_dup(const alpm_depend_t *dep); alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle, alpm_list_t *targets, alpm_list_t *ignore, int reverse); @@ -35,7 +34,6 @@ int _alpm_recursedeps(alpm_db_t *db, alpm_list_t **targs, int include_explicit); int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs, alpm_pkg_t *pkg, alpm_list_t *preferred, alpm_list_t **packages, alpm_list_t *remove, alpm_list_t **data); -alpm_depend_t *_alpm_splitdep(const char *depstring); int _alpm_depcmp_literal(alpm_pkg_t *pkg, alpm_depend_t *dep); int _alpm_depcmp_provides(alpm_depend_t *dep, alpm_list_t *provisions); int _alpm_depcmp(alpm_pkg_t *pkg, alpm_depend_t *dep); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index a69f454..e2997f6 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -630,7 +630,7 @@ cleanup: static void free_deplist(alpm_list_t *deps) { - alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_dep_free); + alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_dep_free); alpm_list_free(deps); } diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 4c74a3a..0c98314 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -524,8 +524,8 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) conflict->package1, conflict->package2); /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ - alpm_depend_t *dep1 = _alpm_splitdep(conflict->package1); - alpm_depend_t *dep2 = _alpm_splitdep(conflict->package2); + alpm_depend_t *dep1 = alpm_dep_from_depstring(conflict->package1); + alpm_depend_t *dep2 = alpm_dep_from_depstring(conflict->package2); if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; @@ -544,12 +544,12 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data) } alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free); alpm_list_free(deps); - _alpm_dep_free(dep1); - _alpm_dep_free(dep2); + alpm_dep_free(dep1); + alpm_dep_free(dep2); goto cleanup; } - _alpm_dep_free(dep1); - _alpm_dep_free(dep2); + alpm_dep_free(dep1); + alpm_dep_free(dep2); /* Prints warning */ _alpm_log(handle, ALPM_LOG_WARNING, -- 2.1.0
This allows to ignore specific dependencies. Signed-off-by: Florian Pritz <bluewind@xinu.at> --- doc/pacman.8.txt | 6 +++ lib/libalpm/alpm.h | 11 +++++ lib/libalpm/deps.c | 8 +++- lib/libalpm/handle.c | 79 ++++++++++++++++++++++++++++++++++ lib/libalpm/handle.h | 1 + src/pacman/conf.c | 17 ++++++++ src/pacman/conf.h | 4 +- src/pacman/pacman.c | 4 ++ test/pacman/tests/TESTS | 3 ++ test/pacman/tests/assumeinstalled.py | 20 +++++++++ test/pacman/tests/assumeinstalled_2.py | 11 +++++ test/pacman/tests/assumeinstalled_3.py | 14 ++++++ 12 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 test/pacman/tests/assumeinstalled.py create mode 100644 test/pacman/tests/assumeinstalled_2.py create mode 100644 test/pacman/tests/assumeinstalled_3.py diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 152b261..45741b4 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -186,6 +186,12 @@ Transaction Options (apply to '-S', '-R' and '-U') dependencies are installed and there are no package conflicts in the system. Specify this option twice to skip all dependency checks. +*\--assume-installed* <package=version>:: + Add a virtual package "package" with version "version" to the transaction + to satisfy dependencies. This allows to disable specific dependency checks + without affecting all dependency checks. To disable all dependency + checking, see the '\--nodeps' option. + *\--dbonly*:: Adds/removes the database entry only, leaving all files in place. diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 12769a4..9a35454 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_assumeinstalled(alpm_handle_t *handle); +int alpm_option_add_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep); +int alpm_option_set_assumeinstalled(alpm_handle_t *handle, alpm_list_t *deps); +int alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *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 0ef5756..55c47a1 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -333,8 +333,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) && + !_alpm_depcmp_provides(depend, handle->assumeinstalled)) { /* Unsatisfied dependency in the upgrade list */ alpm_depmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); @@ -363,9 +365,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) && + !_alpm_depcmp_provides(depend, handle->assumeinstalled)) { 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 fdd269b..0f88462 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -37,6 +37,7 @@ #include "delta.h" #include "trans.h" #include "alpm.h" +#include "deps.h" alpm_handle_t *_alpm_handle_new(void) { @@ -86,6 +87,10 @@ void _alpm_handle_free(alpm_handle_t *handle) FREELIST(handle->noextract); FREELIST(handle->ignorepkg); FREELIST(handle->ignoregroup); + + alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(handle->assumeinstalled); + FREE(handle); } @@ -246,6 +251,30 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle) return handle->ignoregroup; } +alpm_list_t SYMEXPORT *alpm_option_get_assumeinstalled(alpm_handle_t *handle) +{ + alpm_list_t *ret = NULL; + CHECK_HANDLE(handle, return NULL); + + for(alpm_list_t *i = handle->assumeinstalled; i; i = i->next) { + alpm_depend_t *dep = i->data; + char *pkg = NULL; + int len = strlen(dep->name) + strlen("=") + strlen(dep->version) + 1; + MALLOC(pkg, len, goto error); + if(snprintf(pkg, len, "%s=%s", dep->name, dep->version) != len - 1) { + _alpm_log(handle, ALPM_LOG_DEBUG, "Failed to assemble assumeinstalled string\n"); + goto error; + } + ret = alpm_list_add(ret, pkg); + } + return ret; + +error: + alpm_list_free_inner(ret, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(ret); + return NULL; +} + const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) { CHECK_HANDLE(handle, return NULL); @@ -545,6 +574,56 @@ int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char * return _alpm_option_strlist_rem(handle, &(handle->ignoregroup), grp); } +int SYMEXPORT alpm_option_add_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep) +{ + CHECK_HANDLE(handle, return -1); + + handle->assumeinstalled = alpm_list_add(handle->assumeinstalled, (void *)dep); + return 0; +} + +int SYMEXPORT alpm_option_set_assumeinstalled(alpm_handle_t *handle, alpm_list_t *deps) +{ + CHECK_HANDLE(handle, return -1); + if(handle->assumeinstalled) { + alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(handle->assumeinstalled); + } + for(alpm_list_t *i = deps; i; i = i->next) { + int ret = alpm_option_add_assumeinstalled(handle, i->data); + if(ret) { + return ret; + } + } + return 0; +} + +static int assumeinstalled_cmp(const void *data, const void *pkg) +{ + const alpm_depend_t *dep1 = ((alpm_list_t*)data)->data; + const alpm_depend_t *dep2 = pkg; + + if(strcmp(dep1->name, dep2->name) && strcmp(dep1->version, dep2->version)) { + return 0; + } + + return -1; +} + +int SYMEXPORT alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep) +{ + alpm_depend_t *vdata = NULL; + CHECK_HANDLE(handle, return -1); + + handle->assumeinstalled = alpm_list_remove(handle->assumeinstalled, dep, &assumeinstalled_cmp, (void **)&vdata); + if(vdata != NULL) { + alpm_dep_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..c9c454a 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 *assumeinstalled; /* List of virtual packages used to satisfy dependencies */ /* options */ char *arch; /* Architecture of packages we should allow */ diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 0e483f7..4573e8e 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->assumeinstalled); FREELIST(oldconfig->noupgrade); FREELIST(oldconfig->noextract); free(oldconfig->configfile); @@ -741,6 +742,22 @@ static int setup_libalpm(void) alpm_option_set_noupgrades(handle, config->noupgrade); alpm_option_set_noextracts(handle, config->noextract); + for(alpm_list_t *i = config->assumeinstalled; i; i = i->next) { + char *entry = i->data; + alpm_depend_t *dep = alpm_splitdep(entry); + if(!dep) { + pm_printf(ALPM_LOG_WARNING, _("Invalid format for assume installed entry. Skipping '%s'\n"), entry); + alpm_dep_free(dep); + return 1; + } + pm_printf(ALPM_LOG_DEBUG, "parsed assume installed: %s %s\n", dep->name, dep->version); + + ret = alpm_option_add_assumeinstalled(handle, dep); + if(ret) { + return ret; + } + } + return 0; } diff --git a/src/pacman/conf.h b/src/pacman/conf.h index e8cac50..8aed6d6 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 *assumeinstalled; 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_ASSUMEINSTALLED }; /* clean method */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 345fb0a..e079726 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -632,6 +632,9 @@ static int parsearg_trans(int opt) free(config->print_format); config->print_format = strdup(optarg); break; + case OP_ASSUMEINSTALLED: + parsearg_util_addlist(&(config->assumeinstalled)); + break; default: return 1; } @@ -855,6 +858,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}, + {"assume-installed", required_argument, 0, OP_ASSUMEINSTALLED}, {"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 1b5a81f..6c3c548 100644 --- a/test/pacman/tests/TESTS +++ b/test/pacman/tests/TESTS @@ -1,3 +1,6 @@ +TESTS += test/pacman/tests/assumeinstalled.py +TESTS += test/pacman/tests/assumeinstalled_2.py +TESTS += test/pacman/tests/assumeinstalled_3.py TESTS += test/pacman/tests/clean001.py TESTS += test/pacman/tests/clean002.py TESTS += test/pacman/tests/clean003.py diff --git a/test/pacman/tests/assumeinstalled.py b/test/pacman/tests/assumeinstalled.py new file mode 100644 index 0000000..41b7750 --- /dev/null +++ b/test/pacman/tests/assumeinstalled.py @@ -0,0 +1,20 @@ +self.description = "Update a package using --assume-installed" + +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 --assume-installed 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") diff --git a/test/pacman/tests/assumeinstalled_2.py b/test/pacman/tests/assumeinstalled_2.py new file mode 100644 index 0000000..6744dc8 --- /dev/null +++ b/test/pacman/tests/assumeinstalled_2.py @@ -0,0 +1,11 @@ +self.description = "Install a package using --assume-installed" + +sp1 = pmpkg("pkg2", "2.0-1") +sp1.depends = ["pkg1"] + +self.addpkg2db("sync", sp1); + +self.args = "-S pkg2 --assume-installed pkg1" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg2") diff --git a/test/pacman/tests/assumeinstalled_3.py b/test/pacman/tests/assumeinstalled_3.py new file mode 100644 index 0000000..4f3630c --- /dev/null +++ b/test/pacman/tests/assumeinstalled_3.py @@ -0,0 +1,14 @@ +self.description = "Remove a package using --assume-installed" + +lp1 = pmpkg("pkg1", "1.0-1") + +lp2 = pmpkg("pkg2", "1.0-1") +lp2.depends = ["pkg1=1.0"] +for p in lp1, lp2: + self.addpkg2db("local", p); + +self.args = "-R pkg1 --assume-installed pkg1=1.0" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg1") -- 2.1.0
On 09/17/14 at 01:02am, Florian Pritz wrote:
This allows to ignore specific dependencies.
Signed-off-by: Florian Pritz <bluewind@xinu.at> --- doc/pacman.8.txt | 6 +++ lib/libalpm/alpm.h | 11 +++++ lib/libalpm/deps.c | 8 +++- lib/libalpm/handle.c | 79 ++++++++++++++++++++++++++++++++++ lib/libalpm/handle.h | 1 + src/pacman/conf.c | 17 ++++++++ src/pacman/conf.h | 4 +- src/pacman/pacman.c | 4 ++ test/pacman/tests/TESTS | 3 ++ test/pacman/tests/assumeinstalled.py | 20 +++++++++ test/pacman/tests/assumeinstalled_2.py | 11 +++++ test/pacman/tests/assumeinstalled_3.py | 14 ++++++ 12 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 test/pacman/tests/assumeinstalled.py create mode 100644 test/pacman/tests/assumeinstalled_2.py create mode 100644 test/pacman/tests/assumeinstalled_3.py
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 152b261..45741b4 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -186,6 +186,12 @@ Transaction Options (apply to '-S', '-R' and '-U') dependencies are installed and there are no package conflicts in the system. Specify this option twice to skip all dependency checks.
+*\--assume-installed* <package=version>:: + Add a virtual package "package" with version "version" to the transaction + to satisfy dependencies. This allows to disable specific dependency checks + without affecting all dependency checks. To disable all dependency + checking, see the '\--nodeps' option. + *\--dbonly*:: Adds/removes the database entry only, leaving all files in place.
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 12769a4..9a35454 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_assumeinstalled(alpm_handle_t *handle); +int alpm_option_add_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep); +int alpm_option_set_assumeinstalled(alpm_handle_t *handle, alpm_list_t *deps); +int alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *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 0ef5756..55c47a1 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -333,8 +333,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) && + !_alpm_depcmp_provides(depend, handle->assumeinstalled)) { /* Unsatisfied dependency in the upgrade list */ alpm_depmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); @@ -363,9 +365,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) && + !_alpm_depcmp_provides(depend, handle->assumeinstalled)) { 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 fdd269b..0f88462 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -37,6 +37,7 @@ #include "delta.h" #include "trans.h" #include "alpm.h" +#include "deps.h"
alpm_handle_t *_alpm_handle_new(void) { @@ -86,6 +87,10 @@ void _alpm_handle_free(alpm_handle_t *handle) FREELIST(handle->noextract); FREELIST(handle->ignorepkg); FREELIST(handle->ignoregroup); + + alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(handle->assumeinstalled); + FREE(handle); }
@@ -246,6 +251,30 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle) return handle->ignoregroup; }
+alpm_list_t SYMEXPORT *alpm_option_get_assumeinstalled(alpm_handle_t *handle) +{ + alpm_list_t *ret = NULL; + CHECK_HANDLE(handle, return NULL); + + for(alpm_list_t *i = handle->assumeinstalled; i; i = i->next) { + alpm_depend_t *dep = i->data; + char *pkg = NULL; + int len = strlen(dep->name) + strlen("=") + strlen(dep->version) + 1; + MALLOC(pkg, len, goto error); + if(snprintf(pkg, len, "%s=%s", dep->name, dep->version) != len - 1) { + _alpm_log(handle, ALPM_LOG_DEBUG, "Failed to assemble assumeinstalled string\n"); + goto error; + } + ret = alpm_list_add(ret, pkg); + } + return ret; + +error: + alpm_list_free_inner(ret, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(ret); + return NULL;
You're still returning a list of strings...
+} + const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) { CHECK_HANDLE(handle, return NULL); @@ -545,6 +574,56 @@ int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char * return _alpm_option_strlist_rem(handle, &(handle->ignoregroup), grp); }
+int SYMEXPORT alpm_option_add_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep) +{ + CHECK_HANDLE(handle, return -1); + + handle->assumeinstalled = alpm_list_add(handle->assumeinstalled, (void *)dep); + return 0; +} + +int SYMEXPORT alpm_option_set_assumeinstalled(alpm_handle_t *handle, alpm_list_t *deps) +{ + CHECK_HANDLE(handle, return -1); + if(handle->assumeinstalled) { + alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(handle->assumeinstalled); + } + for(alpm_list_t *i = deps; i; i = i->next) { + int ret = alpm_option_add_assumeinstalled(handle, i->data); + if(ret) { + return ret; + } + }
No need to bother with add_assumeinstalled anymore. This can be a simple assignment like (most of) our other setters.
+ return 0; +} + +static int assumeinstalled_cmp(const void *data, const void *pkg)
data and pkg are misleading names, convention would have d1 and d2.
+{ + const alpm_depend_t *dep1 = ((alpm_list_t*)data)->data;
The comparison function gets the list item data, not an alpm_list_t*.
+ const alpm_depend_t *dep2 = pkg; + + if(strcmp(dep1->name, dep2->name) && strcmp(dep1->version, dep2->version)) {
Those should both be strcmp(...) == 0.
+ return 0; + } + + return -1; +} + +int SYMEXPORT alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep) +{ + alpm_depend_t *vdata = NULL; + CHECK_HANDLE(handle, return -1); + + handle->assumeinstalled = alpm_list_remove(handle->assumeinstalled, dep, &assumeinstalled_cmp, (void **)&vdata); + if(vdata != NULL) { + alpm_dep_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..c9c454a 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 *assumeinstalled; /* List of virtual packages used to satisfy dependencies */
/* options */ char *arch; /* Architecture of packages we should allow */ diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 0e483f7..4573e8e 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->assumeinstalled); FREELIST(oldconfig->noupgrade); FREELIST(oldconfig->noextract); free(oldconfig->configfile); @@ -741,6 +742,22 @@ static int setup_libalpm(void) alpm_option_set_noupgrades(handle, config->noupgrade); alpm_option_set_noextracts(handle, config->noextract);
+ for(alpm_list_t *i = config->assumeinstalled; i; i = i->next) {
i should be declared at the top of the block.
+ char *entry = i->data; + alpm_depend_t *dep = alpm_splitdep(entry); + if(!dep) { + pm_printf(ALPM_LOG_WARNING, _("Invalid format for assume installed entry. Skipping '%s'\n"), entry);
This is inconsistent. It's printed as a warning and says it's just skipping the invalid depend but then aborts pacman. Also, please wrap this closer to 80 columns.
+ alpm_dep_free(dep);
dep is NULL, there's nothing to free here.
+ return 1; + } + pm_printf(ALPM_LOG_DEBUG, "parsed assume installed: %s %s\n", dep->name, dep->version); + + ret = alpm_option_add_assumeinstalled(handle, dep); + if(ret) {
dep should be freed here and there should be an error message before aborting.
+ return ret; + } + } + return 0; }
diff --git a/src/pacman/conf.h b/src/pacman/conf.h index e8cac50..8aed6d6 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 *assumeinstalled; 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_ASSUMEINSTALLED };
/* clean method */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 345fb0a..e079726 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -632,6 +632,9 @@ static int parsearg_trans(int opt) free(config->print_format); config->print_format = strdup(optarg); break; + case OP_ASSUMEINSTALLED: + parsearg_util_addlist(&(config->assumeinstalled)); + break; default: return 1; } @@ -855,6 +858,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}, + {"assume-installed", required_argument, 0, OP_ASSUMEINSTALLED}, {"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 1b5a81f..6c3c548 100644 --- a/test/pacman/tests/TESTS +++ b/test/pacman/tests/TESTS @@ -1,3 +1,6 @@ +TESTS += test/pacman/tests/assumeinstalled.py +TESTS += test/pacman/tests/assumeinstalled_2.py +TESTS += test/pacman/tests/assumeinstalled_3.py
These test names don't follow either our previous naming convention or the newer descriptive convention.
TESTS += test/pacman/tests/clean001.py TESTS += test/pacman/tests/clean002.py TESTS += test/pacman/tests/clean003.py diff --git a/test/pacman/tests/assumeinstalled.py b/test/pacman/tests/assumeinstalled.py new file mode 100644 index 0000000..41b7750 --- /dev/null +++ b/test/pacman/tests/assumeinstalled.py @@ -0,0 +1,20 @@ +self.description = "Update a package using --assume-installed" + +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 --assume-installed 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")
PKG_VERSION already requires the package to exist, checking pkg1 again is redundant.
diff --git a/test/pacman/tests/assumeinstalled_2.py b/test/pacman/tests/assumeinstalled_2.py new file mode 100644 index 0000000..6744dc8 --- /dev/null +++ b/test/pacman/tests/assumeinstalled_2.py @@ -0,0 +1,11 @@ +self.description = "Install a package using --assume-installed" + +sp1 = pmpkg("pkg2", "2.0-1") +sp1.depends = ["pkg1"] + +self.addpkg2db("sync", sp1); + +self.args = "-S pkg2 --assume-installed pkg1" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg2") diff --git a/test/pacman/tests/assumeinstalled_3.py b/test/pacman/tests/assumeinstalled_3.py new file mode 100644 index 0000000..4f3630c --- /dev/null +++ b/test/pacman/tests/assumeinstalled_3.py @@ -0,0 +1,14 @@ +self.description = "Remove a package using --assume-installed" + +lp1 = pmpkg("pkg1", "1.0-1") + +lp2 = pmpkg("pkg2", "1.0-1") +lp2.depends = ["pkg1=1.0"] +for p in lp1, lp2: + self.addpkg2db("local", p); + +self.args = "-R pkg1 --assume-installed pkg1=1.0" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg1") -- 2.1.0
This allows to ignore specific dependencies. Signed-off-by: Florian Pritz <bluewind@xinu.at> --- v4: - Incorporate suggestions from Andrew - Return 1 if alpm_dep_from_depstring fails since this can only happen because of memory problems which already generate an error message. I hope this is fine. doc/pacman.8.txt | 6 +++ lib/libalpm/alpm.h | 11 +++++ lib/libalpm/deps.c | 8 +++- lib/libalpm/handle.c | 56 +++++++++++++++++++++++ lib/libalpm/handle.h | 1 + src/pacman/conf.c | 18 ++++++++ src/pacman/conf.h | 4 +- src/pacman/pacman.c | 4 ++ test/pacman/tests/TESTS | 3 ++ test/pacman/tests/remove-assumeinstalled.py | 14 ++++++ test/pacman/tests/sync-install-assumeinstalled.py | 11 +++++ test/pacman/tests/sync-update-assumeinstalled.py | 19 ++++++++ 12 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 test/pacman/tests/remove-assumeinstalled.py create mode 100644 test/pacman/tests/sync-install-assumeinstalled.py create mode 100644 test/pacman/tests/sync-update-assumeinstalled.py diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 152b261..45741b4 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -186,6 +186,12 @@ Transaction Options (apply to '-S', '-R' and '-U') dependencies are installed and there are no package conflicts in the system. Specify this option twice to skip all dependency checks. +*\--assume-installed* <package=version>:: + Add a virtual package "package" with version "version" to the transaction + to satisfy dependencies. This allows to disable specific dependency checks + without affecting all dependency checks. To disable all dependency + checking, see the '\--nodeps' option. + *\--dbonly*:: Adds/removes the database entry only, leaving all files in place. diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 0392cb5..5f08244 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_assumeinstalled(alpm_handle_t *handle); +int alpm_option_add_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep); +int alpm_option_set_assumeinstalled(alpm_handle_t *handle, alpm_list_t *deps); +int alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *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 830a986..e1c38ca 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -333,8 +333,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) && + !_alpm_depcmp_provides(depend, handle->assumeinstalled)) { /* Unsatisfied dependency in the upgrade list */ alpm_depmissing_t *miss; char *missdepstring = alpm_dep_compute_string(depend); @@ -363,9 +365,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) && + !_alpm_depcmp_provides(depend, handle->assumeinstalled)) { 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 fdd269b..de6ce5f 100644 --- a/lib/libalpm/handle.c +++ b/lib/libalpm/handle.c @@ -37,6 +37,7 @@ #include "delta.h" #include "trans.h" #include "alpm.h" +#include "deps.h" alpm_handle_t *_alpm_handle_new(void) { @@ -86,6 +87,10 @@ void _alpm_handle_free(alpm_handle_t *handle) FREELIST(handle->noextract); FREELIST(handle->ignorepkg); FREELIST(handle->ignoregroup); + + alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(handle->assumeinstalled); + FREE(handle); } @@ -246,6 +251,12 @@ alpm_list_t SYMEXPORT *alpm_option_get_ignoregroups(alpm_handle_t *handle) return handle->ignoregroup; } +alpm_list_t SYMEXPORT *alpm_option_get_assumeinstalled(alpm_handle_t *handle) +{ + CHECK_HANDLE(handle, return NULL); + return handle->assumeinstalled; +} + const char SYMEXPORT *alpm_option_get_arch(alpm_handle_t *handle) { CHECK_HANDLE(handle, return NULL); @@ -545,6 +556,51 @@ int SYMEXPORT alpm_option_remove_ignoregroup(alpm_handle_t *handle, const char * return _alpm_option_strlist_rem(handle, &(handle->ignoregroup), grp); } +int SYMEXPORT alpm_option_add_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep) +{ + CHECK_HANDLE(handle, return -1); + + handle->assumeinstalled = alpm_list_add(handle->assumeinstalled, (void *)dep); + return 0; +} + +int SYMEXPORT alpm_option_set_assumeinstalled(alpm_handle_t *handle, alpm_list_t *deps) +{ + CHECK_HANDLE(handle, return -1); + if(handle->assumeinstalled) { + alpm_list_free_inner(handle->assumeinstalled, (alpm_list_fn_free)alpm_dep_free); + alpm_list_free(handle->assumeinstalled); + } + handle->assumeinstalled = deps; + return 0; +} + +static int assumeinstalled_cmp(const void *d1, const void *d2) +{ + const alpm_depend_t *dep1 = d1; + const alpm_depend_t *dep2 = d2; + + if(strcmp(dep1->name, dep2->name) == 0 && strcmp(dep1->version, dep2->version) == 0) { + return 0; + } + + return -1; +} + +int SYMEXPORT alpm_option_remove_assumeinstalled(alpm_handle_t *handle, const alpm_depend_t *dep) +{ + alpm_depend_t *vdata = NULL; + CHECK_HANDLE(handle, return -1); + + handle->assumeinstalled = alpm_list_remove(handle->assumeinstalled, dep, &assumeinstalled_cmp, (void **)&vdata); + if(vdata != NULL) { + alpm_dep_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..c9c454a 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 *assumeinstalled; /* List of virtual packages used to satisfy dependencies */ /* options */ char *arch; /* Architecture of packages we should allow */ diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 0e483f7..d8dfc37 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->assumeinstalled); FREELIST(oldconfig->noupgrade); FREELIST(oldconfig->noextract); free(oldconfig->configfile); @@ -650,6 +651,7 @@ static int setup_libalpm(void) int ret = 0; alpm_errno_t err; alpm_handle_t *handle; + alpm_list_t *i; pm_printf(ALPM_LOG_DEBUG, "setup_libalpm called\n"); @@ -741,6 +743,22 @@ static int setup_libalpm(void) alpm_option_set_noupgrades(handle, config->noupgrade); alpm_option_set_noextracts(handle, config->noextract); + for(i = config->assumeinstalled; i; i = i->next) { + char *entry = i->data; + alpm_depend_t *dep = alpm_dep_from_depstring(entry); + if(!dep) { + return 1; + } + pm_printf(ALPM_LOG_DEBUG, "parsed assume installed: %s %s\n", dep->name, dep->version); + + ret = alpm_option_add_assumeinstalled(handle, dep); + if(ret) { + pm_printf(ALPM_LOG_ERROR, _("Failed to pass assume installed entry to libalpm")); + alpm_dep_free(dep); + return ret; + } + } + return 0; } diff --git a/src/pacman/conf.h b/src/pacman/conf.h index e8cac50..8aed6d6 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 *assumeinstalled; 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_ASSUMEINSTALLED }; /* clean method */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 345fb0a..e079726 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -632,6 +632,9 @@ static int parsearg_trans(int opt) free(config->print_format); config->print_format = strdup(optarg); break; + case OP_ASSUMEINSTALLED: + parsearg_util_addlist(&(config->assumeinstalled)); + break; default: return 1; } @@ -855,6 +858,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}, + {"assume-installed", required_argument, 0, OP_ASSUMEINSTALLED}, {"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 1b5a81f..052cf4b 100644 --- a/test/pacman/tests/TESTS +++ b/test/pacman/tests/TESTS @@ -92,6 +92,7 @@ TESTS += test/pacman/tests/querycheck001.py TESTS += test/pacman/tests/querycheck002.py TESTS += test/pacman/tests/querycheck_fast_file_type.py TESTS += test/pacman/tests/reason001.py +TESTS += test/pacman/tests/remove-assumeinstalled.py TESTS += test/pacman/tests/remove001.py TESTS += test/pacman/tests/remove002.py TESTS += test/pacman/tests/remove010.py @@ -135,12 +136,14 @@ TESTS += test/pacman/tests/symlink010.py TESTS += test/pacman/tests/symlink011.py TESTS += test/pacman/tests/symlink012.py TESTS += test/pacman/tests/symlink020.py +TESTS += test/pacman/tests/sync-install-assumeinstalled.py TESTS += test/pacman/tests/sync-nodepversion01.py TESTS += test/pacman/tests/sync-nodepversion02.py TESTS += test/pacman/tests/sync-nodepversion03.py TESTS += test/pacman/tests/sync-nodepversion04.py TESTS += test/pacman/tests/sync-nodepversion05.py TESTS += test/pacman/tests/sync-nodepversion06.py +TESTS += test/pacman/tests/sync-update-assumeinstalled.py TESTS += test/pacman/tests/sync-update-package-removing-required-provides.py TESTS += test/pacman/tests/sync001.py TESTS += test/pacman/tests/sync002.py diff --git a/test/pacman/tests/remove-assumeinstalled.py b/test/pacman/tests/remove-assumeinstalled.py new file mode 100644 index 0000000..4f3630c --- /dev/null +++ b/test/pacman/tests/remove-assumeinstalled.py @@ -0,0 +1,14 @@ +self.description = "Remove a package using --assume-installed" + +lp1 = pmpkg("pkg1", "1.0-1") + +lp2 = pmpkg("pkg2", "1.0-1") +lp2.depends = ["pkg1=1.0"] +for p in lp1, lp2: + self.addpkg2db("local", p); + +self.args = "-R pkg1 --assume-installed pkg1=1.0" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg1") diff --git a/test/pacman/tests/sync-install-assumeinstalled.py b/test/pacman/tests/sync-install-assumeinstalled.py new file mode 100644 index 0000000..6744dc8 --- /dev/null +++ b/test/pacman/tests/sync-install-assumeinstalled.py @@ -0,0 +1,11 @@ +self.description = "Install a package using --assume-installed" + +sp1 = pmpkg("pkg2", "2.0-1") +sp1.depends = ["pkg1"] + +self.addpkg2db("sync", sp1); + +self.args = "-S pkg2 --assume-installed pkg1" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg2") diff --git a/test/pacman/tests/sync-update-assumeinstalled.py b/test/pacman/tests/sync-update-assumeinstalled.py new file mode 100644 index 0000000..c22a20e --- /dev/null +++ b/test/pacman/tests/sync-update-assumeinstalled.py @@ -0,0 +1,19 @@ +self.description = "Update a package using --assume-installed" + +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 --assume-installed pkg1=1.0" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|2.0-1") +self.addrule("PKG_EXIST=pkg2") -- 2.1.0
participants (5)
-
Allan McRae
-
Andrew Gregory
-
Dave Reisner
-
Florian Pritz
-
Jason St. John