On 18/06/13 08:27, Patrick Steinhardt wrote:
It is now possible to invert patterns in NoExtract. This feature allows users to whitelist certain files that were previously blacklisted by another entry in NoExtract. ---
This patch is another approach to my use case with blacklisting all but some files in /usr/share/locale by being able to invert patterns. An inverted pattern will result in a previously blacklisted file to be whitelisted again. Subsequent matches will always override previous ones. The following NoExtract clause will thus result in all files in /usr/share/locale except en_US/* and locale.alias being skipped:
NoExtract = usr/share/locale/* NoExtract = !usr/share/locale/en_US/* NoExtract = !usr/share/locale/locale.alias
This approach is fine to me. Anyone else want to comment? What needs done: 1) documentation in pacman.conf.5 2) NoUpgrade should be handled exactly the same as NoExtract
lib/libalpm/add.c | 2 +- lib/libalpm/util.c | 32 ++++++++++++++++++++++++++++++++ lib/libalpm/util.h | 1 + 3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index c20e7c6..78f1ae2 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -183,7 +183,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, }
/* if a file is in NoExtract then we never extract it */ - if(alpm_list_find(handle->noextract, entryname, _alpm_fnmatch)) { + if(_alpm_fnmatch_patterns(handle->noextract, entryname) == 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract," " skipping extraction of %s\n", entryname, filename); diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index f84fb66..1382889 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1249,6 +1249,38 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a return ret; }
+/** Checks whether a string matches at least one shell wildcard pattern. + * Checks for matches with fnmatch. Matches are inverted by prepending + * patterns with an exclamation mark. Preceding exclamation marks may be + * escaped. Subsequent matches override previous ones. + * @param patterns patterns to match against + * @param string string to check against pattern + * @return 0 if string matches pattern, negative if they don't match and + * positive if the last match was inverted + */ +int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string) +{ + int result = -1; + alpm_list_t *i; + char *pattern; + short inverted; + + for(i = patterns; i; i = i->next) { + pattern = i->data; + + inverted = pattern[0] == '!'; + if(inverted || pattern[0] == '\\') { + pattern++; + } + + if(_alpm_fnmatch(pattern, string) == 0) { + result = inverted; + } + } + + return result; +} + /** Checks whether a string matches a shell wildcard pattern. * Wrapper around fnmatch. * @param pattern pattern to match against diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 56031f3..24b7c22 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -140,6 +140,7 @@ alpm_time_t _alpm_parsedate(const char *line); int _alpm_raw_cmp(const char *first, const char *second); int _alpm_raw_ncmp(const char *first, const char *second, size_t max); int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode); +int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string); int _alpm_fnmatch(const void *pattern, const void *string);
#ifndef HAVE_STRSEP