[pacman-dev] [PATCH 1/2] libalpm: introduce a disabled status for repos
Disabled repos are still sync'd on a repo refresh, but will never be searched in when looking for package upgrades. A user can still opt to explicitly install something from this repo by using the repo/pkgname format for a target. This patch introduces get/set methods for the disabled attribute on the alpm_db_t object, alpm_db_{get,set}_disabled(). Signed-off-by: Dave Reisner <dreisner@archlinux.org> --- Dan mentioned this in IRC, and I rather liked the idea given how many times I've accidentally updated to [staging]. Ends up being fairly non-invasive, and doesn't require any API breakage. lib/libalpm/alpm.h | 13 +++++++++++++ lib/libalpm/db.c | 16 ++++++++++++++++ lib/libalpm/db.h | 1 + lib/libalpm/deps.c | 15 +++++++++++++-- lib/libalpm/sync.c | 15 +++++++++++++-- test/pacman/tests/sync051.py | 17 +++++++++++++++++ test/pacman/tests/sync052.py | 14 ++++++++++++++ 7 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 test/pacman/tests/sync051.py create mode 100644 test/pacman/tests/sync052.py diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index bb792cf..53bf2a3 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -661,6 +661,19 @@ alpm_list_t *alpm_db_get_groupcache(alpm_db_t *db); */ alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t *needles); +/** Sets the disabled status of a database. + * @param db pointer to the package database to set the status for + * @param disabled a 0 (enabled) or positive integer (disabled) + * @return 0 on success, or -1 on error + */ +int alpm_db_set_disabled(alpm_db_t *db, int disabled); + +/** Gets the disabled status of a database. + * @param db pointer to the package database to get the status of + * @return 0 when enabled, 1 when disabled, -1 on error + */ +int alpm_db_get_disabled(alpm_db_t *db); + /** @} */ /** @addtogroup alpm_api_packages Package Functions diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 8bbdc90..cc205bf 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -289,6 +289,22 @@ alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles) return _alpm_db_search(db, needles); } +/** Sets the disabled status of a repo */ +int SYMEXPORT alpm_db_set_disabled(alpm_db_t *db, int disabled) +{ + ASSERT(db != NULL, return -1); + ASSERT(disabled >= 0, return -1); + db->disabled = !!disabled; + return 0; +} + +/** Gets the disabled status of a repo */ +int SYMEXPORT alpm_db_get_disabled(alpm_db_t *db) +{ + ASSERT(db != NULL, return -1); + return db->disabled; +} + /** @} */ diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 94659b7..76c9fa0 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -73,6 +73,7 @@ struct __alpm_db_t { /* flags determining validity, local, loaded caches, etc. */ enum _alpm_dbstatus_t status; alpm_siglevel_t siglevel; + int disabled; }; diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 2a06bb0..4b953c2 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -589,7 +589,14 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep, /* 1. literals */ for(i = dbs; i; i = i->next) { - alpm_pkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); + alpm_pkg_t *pkg; + alpm_db_t *db = i->data; + + if(db->disabled) { + continue; + } + + pkg = _alpm_db_get_pkgfromcache(db, dep->name); if(pkg && _alpm_depcmp_literal(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(handle, pkg)) { @@ -611,7 +618,11 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep, } /* 2. satisfiers (skip literals here) */ for(i = dbs; i; i = i->next) { - for(j = _alpm_db_get_pkgcache(i->data); j; j = j->next) { + alpm_db_t *db = i->data; + if(db->disabled) { + continue; + } + for(j = _alpm_db_get_pkgcache(db); j; j = j->next) { alpm_pkg_t *pkg = j->data; /* with hash != hash, we can even skip the strcmp() as we know they can't * possibly be the same string */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 66f7ed1..fbf55a9 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -60,7 +60,12 @@ alpm_pkg_t SYMEXPORT *alpm_sync_newversion(alpm_pkg_t *pkg, alpm_list_t *dbs_syn pkg->handle->pm_errno = 0; for(i = dbs_sync; !spkg && i; i = i->next) { - spkg = _alpm_db_get_pkgfromcache(i->data, pkg->name); + alpm_db_t *db = i->data; + if(db->disabled) { + continue; + } + + spkg = _alpm_db_get_pkgfromcache(db, pkg->name); } if(spkg == NULL) { @@ -212,8 +217,14 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) for(j = handle->dbs_sync; j; j = j->next) { alpm_db_t *sdb = j->data; /* Check sdb */ - alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); + alpm_pkg_t *spkg; int literal_upgrade = 0; + + if(sdb->disabled) { + continue; + } + + spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); if(spkg) { literal_upgrade = check_literal(handle, lpkg, spkg, enable_downgrade); if(literal_upgrade) { diff --git a/test/pacman/tests/sync051.py b/test/pacman/tests/sync051.py new file mode 100644 index 0000000..bd99ccc --- /dev/null +++ b/test/pacman/tests/sync051.py @@ -0,0 +1,17 @@ +self.description = "upgrade a package with a disabled repo" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("syncdisabled", sp) + +sp = pmpkg("dummy", "1.0-2") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +self.args = "-S %s" % sp.name + +self.db['syncdisabled'].option['Disabled'] = ['true'] + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-2") diff --git a/test/pacman/tests/sync052.py b/test/pacman/tests/sync052.py new file mode 100644 index 0000000..be35fa7 --- /dev/null +++ b/test/pacman/tests/sync052.py @@ -0,0 +1,14 @@ +self.description = "sysupgrade with a disabled repo" + +sp = pmpkg("dummy", "1.0-2") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +self.args = "-Syu" + +self.db['sync'].option['Disabled'] = ['true'] + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-1") -- 1.7.11.1
Hook up a per-repo 'Disabled' flag in the config for users to mark repos as disabled. This can take a boolean value such as 'yes', 'true', or '1', or the similar negated 'no', 'false', or '0'. Signed-off-by: Dave Reisner <dreisner@archlinux.org> --- It's possible that I'm blowing smoke with my strcasecmp commment... doc/pacman.conf.5.txt | 7 +++++++ src/pacman/conf.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index a9c5db3..cc2d88f 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -226,6 +226,13 @@ even be used for different architectures. Set the signature verification level for this repository. For more information, see <<SC,Package and Database Signature Checking>> below. +*Disabled =* boolean:: + Allows a repository to be marked as disabled. Disabled repositories will + not be searched when looking for updates, but will continue to be refreshed. + This option takes a boolean true or false value. True can be the string + ``1'', ``yes'', or ``true'', case insensitive. False can be the string ``0'', + ``no'', or ``false'', case insensitive. + Package and Database Signature Checking --------------------------------------- The 'SigLevel' directive is valid in both the `[options]` and repository diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 4aaacb5..4d042aa 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -636,6 +636,7 @@ struct section_t { /* db section option gathering */ alpm_siglevel_t siglevel; alpm_list_t *servers; + int disabled; }; /** @@ -669,6 +670,8 @@ static int finish_section(struct section_t *section, int parse_options) goto cleanup; } + alpm_db_set_disabled(db, section->disabled); + for(i = section->servers; i; i = alpm_list_next(i)) { char *value = i->data; if(_add_mirror(db, value) != 0) { @@ -687,9 +690,29 @@ cleanup: section->siglevel = ALPM_SIG_USE_DEFAULT; free(section->name); section->name = NULL; + section->disabled = 0; return ret; } +static int string_to_boolean(const char *string) +{ + /* usage of strcasecmp here is allowed since we're comparing + * against fixed strings */ + if(strcasecmp(string, "1") == 0 || + strcasecmp(string, "true") == 0 || + strcasecmp(string, "yes") == 0) { + return 1; + } + + if(strcasecmp(string, "0") == 0 || + strcasecmp(string, "false") == 0 || + strcasecmp(string, "no") == 0) { + return 0; + } + + return -1; +} + /** The "real" parseconfig. Each "Include" directive will recall this method so * recursion and stack depth are limited to 10 levels. The publicly visible * parseconfig calls this with a NULL section argument so we can recall from @@ -856,6 +879,21 @@ static int _parseconfig(const char *file, struct section_t *section, } FREELIST(values); } + } else if(strcmp(key, "Disabled") == 0) { + if(value == NULL) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), + file, linenum, key); + ret = 1; + goto cleanup; + } + section->disabled = string_to_boolean(value); + if (section->disabled < 0) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' has " + "invalid boolean value %s\n"), + file, linenum, key, value); + ret = 1; + goto cleanup; + } } else { pm_printf(ALPM_LOG_WARNING, _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), -- 1.7.11.1
On 03/07/12 09:45, Dave Reisner wrote:
Hook up a per-repo 'Disabled' flag in the config for users to mark repos as disabled. This can take a boolean value such as 'yes', 'true', or '1', or the similar negated 'no', 'false', or '0'.
Why do we need this complexity? Why not just specifying "Disabled" disables the repo and not specifying does not...
Signed-off-by: Dave Reisner <dreisner@archlinux.org> --- It's possible that I'm blowing smoke with my strcasecmp commment...
doc/pacman.conf.5.txt | 7 +++++++ src/pacman/conf.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+)
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index a9c5db3..cc2d88f 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -226,6 +226,13 @@ even be used for different architectures. Set the signature verification level for this repository. For more information, see <<SC,Package and Database Signature Checking>> below.
+*Disabled =* boolean:: + Allows a repository to be marked as disabled. Disabled repositories will + not be searched when looking for updates, but will continue to be refreshed. + This option takes a boolean true or false value. True can be the string + ``1'', ``yes'', or ``true'', case insensitive. False can be the string ``0'', + ``no'', or ``false'', case insensitive. + Package and Database Signature Checking --------------------------------------- The 'SigLevel' directive is valid in both the `[options]` and repository diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 4aaacb5..4d042aa 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -636,6 +636,7 @@ struct section_t { /* db section option gathering */ alpm_siglevel_t siglevel; alpm_list_t *servers; + int disabled; };
/** @@ -669,6 +670,8 @@ static int finish_section(struct section_t *section, int parse_options) goto cleanup; }
+ alpm_db_set_disabled(db, section->disabled); + for(i = section->servers; i; i = alpm_list_next(i)) { char *value = i->data; if(_add_mirror(db, value) != 0) { @@ -687,9 +690,29 @@ cleanup: section->siglevel = ALPM_SIG_USE_DEFAULT; free(section->name); section->name = NULL; + section->disabled = 0; return ret; }
+static int string_to_boolean(const char *string) +{ + /* usage of strcasecmp here is allowed since we're comparing + * against fixed strings */ + if(strcasecmp(string, "1") == 0 || + strcasecmp(string, "true") == 0 || + strcasecmp(string, "yes") == 0) { + return 1; + } + + if(strcasecmp(string, "0") == 0 || + strcasecmp(string, "false") == 0 || + strcasecmp(string, "no") == 0) { + return 0; + } + + return -1; +} + /** The "real" parseconfig. Each "Include" directive will recall this method so * recursion and stack depth are limited to 10 levels. The publicly visible * parseconfig calls this with a NULL section argument so we can recall from @@ -856,6 +879,21 @@ static int _parseconfig(const char *file, struct section_t *section, } FREELIST(values); } + } else if(strcmp(key, "Disabled") == 0) { + if(value == NULL) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), + file, linenum, key); + ret = 1; + goto cleanup; + } + section->disabled = string_to_boolean(value); + if (section->disabled < 0) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' has " + "invalid boolean value %s\n"), + file, linenum, key, value); + ret = 1; + goto cleanup; + } } else { pm_printf(ALPM_LOG_WARNING, _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
On Tue, Jul 03, 2012 at 10:02:03AM +1000, Allan McRae wrote:
On 03/07/12 09:45, Dave Reisner wrote:
Hook up a per-repo 'Disabled' flag in the config for users to mark repos as disabled. This can take a boolean value such as 'yes', 'true', or '1', or the similar negated 'no', 'false', or '0'.
Why do we need this complexity? Why not just specifying "Disabled" disables the repo and not specifying does not...
We may not. Dan brought up the idea of making this a bit more granular, but I don't have my IRC logs to recall exactly what was mentioned... he can weigh in here.
Signed-off-by: Dave Reisner <dreisner@archlinux.org> --- It's possible that I'm blowing smoke with my strcasecmp commment...
doc/pacman.conf.5.txt | 7 +++++++ src/pacman/conf.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+)
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index a9c5db3..cc2d88f 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -226,6 +226,13 @@ even be used for different architectures. Set the signature verification level for this repository. For more information, see <<SC,Package and Database Signature Checking>> below.
+*Disabled =* boolean:: + Allows a repository to be marked as disabled. Disabled repositories will + not be searched when looking for updates, but will continue to be refreshed. + This option takes a boolean true or false value. True can be the string + ``1'', ``yes'', or ``true'', case insensitive. False can be the string ``0'', + ``no'', or ``false'', case insensitive. + Package and Database Signature Checking --------------------------------------- The 'SigLevel' directive is valid in both the `[options]` and repository diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 4aaacb5..4d042aa 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -636,6 +636,7 @@ struct section_t { /* db section option gathering */ alpm_siglevel_t siglevel; alpm_list_t *servers; + int disabled; };
/** @@ -669,6 +670,8 @@ static int finish_section(struct section_t *section, int parse_options) goto cleanup; }
+ alpm_db_set_disabled(db, section->disabled); + for(i = section->servers; i; i = alpm_list_next(i)) { char *value = i->data; if(_add_mirror(db, value) != 0) { @@ -687,9 +690,29 @@ cleanup: section->siglevel = ALPM_SIG_USE_DEFAULT; free(section->name); section->name = NULL; + section->disabled = 0; return ret; }
+static int string_to_boolean(const char *string) +{ + /* usage of strcasecmp here is allowed since we're comparing + * against fixed strings */ + if(strcasecmp(string, "1") == 0 || + strcasecmp(string, "true") == 0 || + strcasecmp(string, "yes") == 0) { + return 1; + } + + if(strcasecmp(string, "0") == 0 || + strcasecmp(string, "false") == 0 || + strcasecmp(string, "no") == 0) { + return 0; + } + + return -1; +} + /** The "real" parseconfig. Each "Include" directive will recall this method so * recursion and stack depth are limited to 10 levels. The publicly visible * parseconfig calls this with a NULL section argument so we can recall from @@ -856,6 +879,21 @@ static int _parseconfig(const char *file, struct section_t *section, } FREELIST(values); } + } else if(strcmp(key, "Disabled") == 0) { + if(value == NULL) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value\n"), + file, linenum, key); + ret = 1; + goto cleanup; + } + section->disabled = string_to_boolean(value); + if (section->disabled < 0) { + pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' has " + "invalid boolean value %s\n"), + file, linenum, key, value); + ret = 1; + goto cleanup; + } } else { pm_printf(ALPM_LOG_WARNING, _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"),
On Mon, Jul 2, 2012 at 7:15 PM, Dave Reisner <d@falconindy.com> wrote:
On Tue, Jul 03, 2012 at 10:02:03AM +1000, Allan McRae wrote:
On 03/07/12 09:45, Dave Reisner wrote:
Hook up a per-repo 'Disabled' flag in the config for users to mark repos as disabled. This can take a boolean value such as 'yes', 'true', or '1', or the similar negated 'no', 'false', or '0'.
Why do we need this complexity? Why not just specifying "Disabled" disables the repo and not specifying does not...
We may not. Dan brought up the idea of making this a bit more granular, but I don't have my IRC logs to recall exactly what was mentioned... he can weigh in here.
Given that we have no key-only options under repos, I'm leaning against having those be introduced. I've never been a fan of them in the [options] section either. -Dan
On 03/07/12 10:22, Dan McGee wrote:
On Mon, Jul 2, 2012 at 7:15 PM, Dave Reisner <d@falconindy.com> wrote:
On Tue, Jul 03, 2012 at 10:02:03AM +1000, Allan McRae wrote:
On 03/07/12 09:45, Dave Reisner wrote:
Hook up a per-repo 'Disabled' flag in the config for users to mark repos as disabled. This can take a boolean value such as 'yes', 'true', or '1', or the similar negated 'no', 'false', or '0'.
Why do we need this complexity? Why not just specifying "Disabled" disables the repo and not specifying does not...
We may not. Dan brought up the idea of making this a bit more granular, but I don't have my IRC logs to recall exactly what was mentioned... he can weigh in here.
Given that we have no key-only options under repos, I'm leaning against having those be introduced. I've never been a fan of them in the [options] section either.
OK. But do we really need all of True/Yes/1 etc. I just find that confusing compared to a single "Disabled" flag. How about: Usage = All (default) Usage = Search Install Update Allan
On Tue, Jul 03, 2012 at 10:50:51AM +1000, Allan McRae wrote:
On 03/07/12 10:22, Dan McGee wrote:
On Mon, Jul 2, 2012 at 7:15 PM, Dave Reisner <d@falconindy.com> wrote:
On Tue, Jul 03, 2012 at 10:02:03AM +1000, Allan McRae wrote:
On 03/07/12 09:45, Dave Reisner wrote:
Hook up a per-repo 'Disabled' flag in the config for users to mark repos as disabled. This can take a boolean value such as 'yes', 'true', or '1', or the similar negated 'no', 'false', or '0'.
Why do we need this complexity? Why not just specifying "Disabled" disables the repo and not specifying does not...
We may not. Dan brought up the idea of making this a bit more granular, but I don't have my IRC logs to recall exactly what was mentioned... he can weigh in here.
Given that we have no key-only options under repos, I'm leaning against having those be introduced. I've never been a fan of them in the [options] section either.
OK. But do we really need all of True/Yes/1 etc. I just find that confusing compared to a single "Disabled" flag.
How about: Usage = All (default) Usage = Search Install Update
Allan
I think I like this. /me starts a new branch...
This defines a level of interest a user has in a repository. These are described by the bitmask flags in the alpm_db_usage_t enum: ALPM_DB_USAGE_SEARCH: repo is valid for searching ALPM_DB_USAGE_INSTALL: repo is valid for installs (e.g. -S pkg) ALPM_DB_USAGE_UPGRADE: repo is valid for sysupgrades ALPM_DB_USAGE_ALL: all of the above are valid Explicitly listing the contents of a repo will always be valid, and the repo will always be refreshed appropriately on sync operations. Signed-off-by: Dave Reisner <dreisner@archlinux.org> --- @Allan: I'll see your bikeshed, and raise you a new patchset. There's still a bit of wonky behavior in here, notably: * Specifying only "Search" for a repo won't let you explicitly install from it. I'm not sure I like this. Opinions welcome. * Specifying only "Upgrade" probably results in some odd behavior that I haven't found yet. Should "Upgrade" and "Install" maybe imply "Search"? * The accessor method is probably wrong since it returns a signed integer on failure. There's also definitely a need for some more tests, too. I only refactored the 2 I created for the last patchset (and only roughly). If we can hash out the wanted behavior, I'll finish those up. lib/libalpm/alpm.h | 20 ++++++++++++++++++++ lib/libalpm/be_local.c | 1 + lib/libalpm/db.c | 20 ++++++++++++++++++++ lib/libalpm/db.h | 1 + lib/libalpm/deps.c | 15 +++++++++++++-- lib/libalpm/sync.c | 15 +++++++++++++-- test/pacman/tests/sync051.py | 17 +++++++++++++++++ test/pacman/tests/sync052.py | 14 ++++++++++++++ 8 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 test/pacman/tests/sync051.py create mode 100644 test/pacman/tests/sync052.py diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index bb792cf..381f546 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -661,6 +661,26 @@ alpm_list_t *alpm_db_get_groupcache(alpm_db_t *db); */ alpm_list_t *alpm_db_search(alpm_db_t *db, const alpm_list_t *needles); +typedef enum _alpm_db_usage_ { + ALPM_DB_USAGE_SEARCH = (1 << 0), + ALPM_DB_USAGE_INSTALL = (1 << 1), + ALPM_DB_USAGE_UPGRADE = (1 << 2), + ALPM_DB_USAGE_ALL = (1 << 3) - 1, +} alpm_db_usage_t; + +/** Sets the usage of a database. + * @param db pointer to the package database to set the status for + * @param usage a bitmask of alpm_db_usage_t values + * @return 0 on success, or -1 on error + */ +int alpm_db_set_usage(alpm_db_t *db, alpm_db_usage_t usage); + +/** Gets the usage of a database. + * @param db pointer to the package database to get the status of + * @return a bitmask described by alpm_db_usage_t, or -1 on error + */ +alpm_db_usage_t alpm_db_get_usage(alpm_db_t *db); + /** @} */ /** @addtogroup alpm_api_packages Package Functions diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index ee805b9..47843ad 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -1011,6 +1011,7 @@ alpm_db_t *_alpm_db_register_local(alpm_handle_t *handle) } db->ops = &local_db_ops; db->handle = handle; + db->usage = ALPM_DB_USAGE_ALL; if(local_db_validate(db)) { /* pm_errno set in local_db_validate() */ diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c index 8bbdc90..584698f 100644 --- a/lib/libalpm/db.c +++ b/lib/libalpm/db.c @@ -289,6 +289,21 @@ alpm_list_t SYMEXPORT *alpm_db_search(alpm_db_t *db, const alpm_list_t* needles) return _alpm_db_search(db, needles); } +/** Sets the usage bitmask for a repo */ +int SYMEXPORT alpm_db_set_usage(alpm_db_t *db, alpm_db_usage_t usage) +{ + ASSERT(db != NULL, return -1); + db->usage = usage; + return 0; +} + +/** Gets the usage bitmask for a repo */ +alpm_db_usage_t SYMEXPORT alpm_db_get_usage(alpm_db_t *db) +{ + ASSERT(db != NULL, return -1); + return db->usage; +} + /** @} */ @@ -362,6 +377,11 @@ alpm_list_t *_alpm_db_search(alpm_db_t *db, const alpm_list_t *needles) { const alpm_list_t *i, *j, *k; alpm_list_t *ret = NULL; + + if(!(db->usage & ALPM_DB_USAGE_SEARCH)) { + return NULL; + } + /* copy the pkgcache- we will free the list var after each needle */ alpm_list_t *list = alpm_list_copy(_alpm_db_get_pkgcache(db)); diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h index 94659b7..c1067cb 100644 --- a/lib/libalpm/db.h +++ b/lib/libalpm/db.h @@ -73,6 +73,7 @@ struct __alpm_db_t { /* flags determining validity, local, loaded caches, etc. */ enum _alpm_dbstatus_t status; alpm_siglevel_t siglevel; + alpm_db_usage_t usage; }; diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 2a06bb0..6bfc579 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -589,7 +589,14 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep, /* 1. literals */ for(i = dbs; i; i = i->next) { - alpm_pkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); + alpm_pkg_t *pkg; + alpm_db_t *db = i->data; + + if(!(db->usage & (ALPM_DB_USAGE_INSTALL|ALPM_DB_USAGE_UPGRADE))) { + continue; + } + + pkg = _alpm_db_get_pkgfromcache(db, dep->name); if(pkg && _alpm_depcmp_literal(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(handle, pkg)) { @@ -611,7 +618,11 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep, } /* 2. satisfiers (skip literals here) */ for(i = dbs; i; i = i->next) { - for(j = _alpm_db_get_pkgcache(i->data); j; j = j->next) { + alpm_db_t *db = i->data; + if(!(db->usage & (ALPM_DB_USAGE_INSTALL|ALPM_DB_USAGE_UPGRADE))) { + continue; + } + for(j = _alpm_db_get_pkgcache(db); j; j = j->next) { alpm_pkg_t *pkg = j->data; /* with hash != hash, we can even skip the strcmp() as we know they can't * possibly be the same string */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 66f7ed1..b7809ee 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -60,7 +60,12 @@ alpm_pkg_t SYMEXPORT *alpm_sync_newversion(alpm_pkg_t *pkg, alpm_list_t *dbs_syn pkg->handle->pm_errno = 0; for(i = dbs_sync; !spkg && i; i = i->next) { - spkg = _alpm_db_get_pkgfromcache(i->data, pkg->name); + alpm_db_t *db = i->data; + if(!(db->usage & ALPM_DB_USAGE_SEARCH)) { + continue; + } + + spkg = _alpm_db_get_pkgfromcache(db, pkg->name); } if(spkg == NULL) { @@ -212,8 +217,14 @@ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) for(j = handle->dbs_sync; j; j = j->next) { alpm_db_t *sdb = j->data; /* Check sdb */ - alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); + alpm_pkg_t *spkg; int literal_upgrade = 0; + + if(!(sdb->usage & ALPM_DB_USAGE_UPGRADE)) { + continue; + } + + spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); if(spkg) { literal_upgrade = check_literal(handle, lpkg, spkg, enable_downgrade); if(literal_upgrade) { diff --git a/test/pacman/tests/sync051.py b/test/pacman/tests/sync051.py new file mode 100644 index 0000000..8908dd9 --- /dev/null +++ b/test/pacman/tests/sync051.py @@ -0,0 +1,17 @@ +self.description = "upgrade a package with a disabled repo" + +sp = pmpkg("dummy", "2.0-1") +self.addpkg2db("syncdisabled", sp) + +sp = pmpkg("dummy", "1.0-2") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +self.args = "-S %s" % sp.name + +self.db['syncdisabled'].option['Usage'] = ['Search'] + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-2") diff --git a/test/pacman/tests/sync052.py b/test/pacman/tests/sync052.py new file mode 100644 index 0000000..6ac8fe2 --- /dev/null +++ b/test/pacman/tests/sync052.py @@ -0,0 +1,14 @@ +self.description = "sysupgrade with a disabled repo" + +sp = pmpkg("dummy", "1.0-2") +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy", "1.0-1") +self.addpkg2db("local", lp) + +self.args = "-Syu" + +self.db['sync'].option['Usage'] = ['Search'] + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-1") -- 1.7.11.1
Add a "Usage" key to the repo section of the config which allows for the tokens "Search", "Install", "Upgrade", "All", which correspond to values in the alpm_db_usage_t enum. Users can specify "Usage" multiple times for a given repo, or multiple flags per "Usage" line and they will be OR'd together. If unspecified, the default is full usage of the repo. Signed-off-by: Dave Reisner <dreisner@archlinux.org> --- I'm wondering if there ought to be a way to specify 'None' here, which would basically restrict you to only listing the contents of a repo and nothing else. doc/pacman.conf.5.txt | 16 ++++++++++++++++ src/pacman/conf.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index a9c5db3..4f50df9 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -226,6 +226,22 @@ even be used for different architectures. Set the signature verification level for this repository. For more information, see <<SC,Package and Database Signature Checking>> below. +*Usage =* ...:: + Set the usage level for this repository. This option takes a list of tokens + which can be any of the following: + *Search*;; + Enables searching for this repository. + *Install*;; + Enables installation of packages from this repository during a '\--sync' + operation. + *Upgrade*;; + Allows this repository to be a valid source of packages when performing + a '\--sysupgrade'. + *All*;; + Enables all of the above features for the repository. This is the default + if not specified. + + Package and Database Signature Checking --------------------------------------- The 'SigLevel' directive is valid in both the `[options]` and repository diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 4aaacb5..00df6f8 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -636,6 +636,7 @@ struct section_t { /* db section option gathering */ alpm_siglevel_t siglevel; alpm_list_t *servers; + alpm_db_usage_t usage; }; /** @@ -669,6 +670,12 @@ static int finish_section(struct section_t *section, int parse_options) goto cleanup; } + pm_printf(ALPM_LOG_DEBUG, + "setting usage of %d for %s repoistory\n", + section->usage == 0 ? ALPM_DB_USAGE_ALL : section->usage, + section->name); + alpm_db_set_usage(db, section->usage == 0 ? ALPM_DB_USAGE_ALL : section->usage); + for(i = section->servers; i; i = alpm_list_next(i)) { char *value = i->data; if(_add_mirror(db, value) != 0) { @@ -687,6 +694,38 @@ cleanup: section->siglevel = ALPM_SIG_USE_DEFAULT; free(section->name); section->name = NULL; + section->usage = 0; + return ret; +} + +static int process_usage(alpm_list_t *values, alpm_db_usage_t *usage, + const char *file, int linenum) +{ + alpm_list_t *i; + alpm_db_usage_t level = *usage; + int ret = 0; + + for(i = values; i; i = i->next) { + char *key = i->data; + + if(strcmp(key, "Search") == 0) { + level |= ALPM_DB_USAGE_SEARCH; + } else if(strcmp(key, "Install") == 0) { + level |= ALPM_DB_USAGE_INSTALL; + } else if(strcmp(key, "Upgrade") == 0) { + level |= ALPM_DB_USAGE_UPGRADE; + } else if(strcmp(key, "All") == 0) { + level |= ALPM_DB_USAGE_ALL; + } else { + pm_printf(ALPM_LOG_WARNING, + _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), + file, linenum, key, "options"); + ret = 1; + } + } + + *usage = level; + return ret; } @@ -856,6 +895,17 @@ static int _parseconfig(const char *file, struct section_t *section, } FREELIST(values); } + } else if(strcmp(key, "Usage") == 0) { + alpm_list_t *values = NULL; + setrepeatingoption(value, "Usage", &values); + if(values) { + if(process_usage(values, §ion->usage, file, linenum)) { + FREELIST(values); + ret = 1; + goto cleanup; + } + FREELIST(values); + } } else { pm_printf(ALPM_LOG_WARNING, _("config file %s, line %d: directive '%s' in section '%s' not recognized.\n"), @@ -886,6 +936,7 @@ int parseconfig(const char *file) struct section_t section; memset(§ion, 0, sizeof(struct section_t)); section.siglevel = ALPM_SIG_USE_DEFAULT; + section.usage = 0; /* the config parse is a two-pass affair. We first parse the entire thing for * the [options] section so we can get all default and path options set. * Next, we go back and parse everything but [options]. */ -- 1.7.11.1
participants (4)
-
Allan McRae
-
Dan McGee
-
Dave Reisner
-
Dave Reisner