Linux Archive

Linux Archive (http://www.linux-archive.org/)
-   ArchLinux Pacman Development (http://www.linux-archive.org/archlinux-pacman-development/)
-   -   Fix parsing included files w/ sections (http://www.linux-archive.org/archlinux-pacman-development/619909-fix-parsing-included-files-w-sections.html)

Olivier Brunel 01-11-2012 05:52 PM

Fix parsing included files w/ sections
 
When parsing Include directives, a new section_t is now
used, to ensure it won't "mess" with the current one (since
included files can define new sections, which would result
in an invalid "change" of the current section) This new
section starts "in" the current one (so included files are
parsed as expected, and don't need to open any section);
IOW sections propagate down the include chain, not back up.

This also solves the bug (?) when two repos with the same name are declared,
which could happen in the same file or, more likely, through Include-s.
Now only one db will be registered, with all servers in it (it used to
be as many dbs with the same name as there were sections).

Signed-off-by: Olivier Brunel <i.am.jack.mail@gmail.com>
---
src/pacman/conf.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 2ff16d2..eb3374e 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -628,6 +628,18 @@ struct section_t {
alpm_list_t *servers;
};

+static alpm_db_t *get_db(const char *dbname)
+{
+ alpm_list_t *i;
+ for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) {
+ alpm_db_t *db = i->data;
+ if(strcmp(alpm_db_get_name(db), dbname) == 0) {
+ return db;
+ }
+ }
+ return NULL;
+}
+
/**
* Wrap up a section once we have reached the end of it. This should be called
* when a subsequent section is encountered, or when we have reached the end of
@@ -650,13 +662,17 @@ static int finish_section(struct section_t *section, int parse_options)
goto cleanup;
}

- /* if we are not looking at options sections only, register a db */
- db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
+ /* if we are not looking at options sections only, get the db */
+ db = get_db(section->name);
if(db == NULL) {
- pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
- section->name, alpm_strerror(alpm_errno(config->handle)));
- ret = 1;
- goto cleanup;
+ /* not registered yet, let's do it */
+ db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
+ if(db == NULL) {
+ pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
+ section->name, alpm_strerror(alpm_errno(config->handle)));
+ ret = 1;
+ goto cleanup;
+ }
}

for(i = section->servers; i; i = alpm_list_next(i)) {
@@ -780,6 +796,7 @@ static int _parseconfig(const char *file, struct section_t *section,
glob_t globbuf;
int globret;
size_t gindex;
+ struct section_t inc_section;

if(value == NULL) {
pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value
"),
@@ -816,10 +833,33 @@ static int _parseconfig(const char *file, struct section_t *section,
file, linenum, value);
break;
default:
+ /* create new section_t for the includes -- to keep ours unaffected */
for(gindex = 0; gindex < globbuf.gl_pathc; gindex++) {
+ /* we use a different section_t for includes, so they can't mess up
+ * the current one. This section starts "in" the current section ofc */
+ inc_section->name = strdup (section->name);
+ inc_section->is_options = section->is_options;
+ inc_section->siglevel = section->siglevel;
+ inc_section->servers = NULL;
pm_printf(ALPM_LOG_DEBUG, "config file %s, line %d: including %s
",
file, linenum, globbuf.gl_pathv[gindex]);
- _parseconfig(globbuf.gl_pathv[gindex], section, parse_options, depth + 1);
+ _parseconfig(globbuf.gl_pathv[gindex], inc_section, parse_options, depth + 1);
+ /* now, if this is a repo ... */
+ if(!parse_options && !section->is_options) {
+ if (section->siglevel == inc_section->siglevel
+ && strcmp(section->name, inc_section->name) == 0) {
+ /* ... still the same one, we'll just import servers */
+ alpm_list_t *i;
+ for(i = inc_section->servers; i; i = alpm_list_next(i)) {
+ section->servers = alpm_list_add(section->servers, i->data);
+ }
+ alpm_list_free(inc_section->servers);
+ free(inc_section->name);
+ } else {
+ /* ... a different one, so let's "finish" it */
+ finish_section(inc_section, parse_options);
+ }
+ }
}
break;
}
--
1.7.8.3

Dan McGee 01-11-2012 09:00 PM

Fix parsing included files w/ sections
 
On Wed, Jan 11, 2012 at 12:52 PM, Olivier Brunel
<i.am.jack.mail@gmail.com> wrote:
> When parsing Include directives, a new section_t is now
> used, to ensure it won't "mess" with the current one (since
> included files can define new sections, which would result
> in an invalid "change" of the current section) This new
> section starts "in" the current one (so included files are
> parsed as expected, and don't need to open any section);
> IOW sections propagate down the include chain, not back up.
>
> This also solves the bug (?) when two repos with the same name are declared,
> which could happen in the same file or, more likely, through Include-s.
> Now only one db will be registered, with all servers in it (it used to
> be as many dbs with the same name as there were sections).

IOW? bug (?)? "quotes" around "random" words? I know I'm nitpicking,
but this is not always the most readable English, especially to
non-native speakers (even I had to look up what IOW was).

Imagine coming back to a commit message in two years- if there is
anything in it that wouldn't make sense, you need to reword/rewrite
it. That is the purpose of commit messages.

> Signed-off-by: Olivier Brunel <i.am.jack.mail@gmail.com>
> ---
> *src/pacman/conf.c | * 54 ++++++++++++++++++++++++++++++++++++++++++++++------
> *1 files changed, 47 insertions(+), 7 deletions(-)
>
> diff --git a/src/pacman/conf.c b/src/pacman/conf.c
> index 2ff16d2..eb3374e 100644
> --- a/src/pacman/conf.c
> +++ b/src/pacman/conf.c
> @@ -628,6 +628,18 @@ struct section_t {
> * * * *alpm_list_t *servers;
> *};
>
> +static alpm_db_t *get_db(const char *dbname)
> +{
> + * * * alpm_list_t *i;
> + * * * for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) {
> + * * * * * * * alpm_db_t *db = i->data;
> + * * * * * * * if(strcmp(alpm_db_get_name(db), dbname) == 0) {
> + * * * * * * * * * * * return db;
> + * * * * * * * }
> + * * * }
> + * * * return NULL;
> +}
Rather than copying this straight out of src/pacman/sync.c, why don't
you make it visible to the entire compilation unit in util.c/util.h
(this file) and remove the now unneeded version from sync.c? (for a
more public function, a longer name might be nice too; something like
'get_sync_db' just to be as clear as possible).

> +
> */**
> ** Wrap up a section once we have reached the end of it. This should be called
> ** when a subsequent section is encountered, or when we have reached the end of
> @@ -650,13 +662,17 @@ static int finish_section(struct section_t *section, int parse_options)
> * * * * * * * *goto cleanup;
> * * * *}
>
> - * * * /* if we are not looking at options sections only, register a db */
> - * * * db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
> + * * * /* if we are not looking at options sections only, get the db */
> + * * * db = get_db(section->name);
> * * * *if(db == NULL) {
> - * * * * * * * pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
> - * * * * * * * * * * * * * * * section->name, alpm_strerror(alpm_errno(config->handle)));
> - * * * * * * * ret = 1;
> - * * * * * * * goto cleanup;
> + * * * * * * * /* not registered yet, let's do it */
The "let's do it" part is not really necessary; I say this because we
also try to avoid contractions if possible.

> + * * * * * * * db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
> + * * * * * * * if(db == NULL) {
> + * * * * * * * * * * * pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
> + * * * * * * * * * * * * * * * * * * * section->name, alpm_strerror(alpm_errno(config->handle)));
> + * * * * * * * * * * * ret = 1;
> + * * * * * * * * * * * goto cleanup;
> + * * * * * * * }
> * * * *}
>
> * * * *for(i = section->servers; i; i = alpm_list_next(i)) {
> @@ -780,6 +796,7 @@ static int _parseconfig(const char *file, struct section_t *section,
> * * * * * * * * * * * *glob_t globbuf;
> * * * * * * * * * * * *int globret;
> * * * * * * * * * * * *size_t gindex;
> + * * * * * * * * * * * struct section_t inc_section;
>
> * * * * * * * * * * * *if(value == NULL) {
> * * * * * * * * * * * * * * * *pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value
"),
> @@ -816,10 +833,33 @@ static int _parseconfig(const char *file, struct section_t *section,
> * * * * * * * * * * * * * * * * * * * * * * * * * * * *file, linenum, value);
> * * * * * * * * * * * * * * * *break;
> * * * * * * * * * * * * * * * *default:
> + * * * * * * * * * * * * * * * * * * * /* create new section_t for the includes -- to keep ours unaffected */
> * * * * * * * * * * * * * * * * * * * *for(gindex = 0; gindex < globbuf.gl_pathc; gindex++) {
> + * * * * * * * * * * * * * * * * * * * * * * * /* we use a different section_t for includes, so they can't mess up
> + * * * * * * * * * * * * * * * * * * * * * * * ** the current one. This section starts "in" the current section ofc */
ofc?

> + * * * * * * * * * * * * * * * * * * * * * * * inc_section->name = strdup (section->name);
> + * * * * * * * * * * * * * * * * * * * * * * * inc_section->is_options = section->is_options;
> + * * * * * * * * * * * * * * * * * * * * * * * inc_section->siglevel = section->siglevel;
> + * * * * * * * * * * * * * * * * * * * * * * * inc_section->servers = NULL;
> * * * * * * * * * * * * * * * * * * * * * * * *pm_printf(ALPM_LOG_DEBUG, "config file %s, line %d: including %s
",
> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *file, linenum, globbuf.gl_pathv[gindex]);
> - * * * * * * * * * * * * * * * * * * * * * * * _parseconfig(globbuf.gl_pathv[gindex], section, parse_options, depth + 1);
> + * * * * * * * * * * * * * * * * * * * * * * * _parseconfig(globbuf.gl_pathv[gindex], inc_section, parse_options, depth + 1);
> + * * * * * * * * * * * * * * * * * * * * * * * /* now, if this is a repo ... */
> + * * * * * * * * * * * * * * * * * * * * * * * if(!parse_options && !section->is_options) {
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * if (section->siglevel == inc_section->siglevel
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * && strcmp(section->name, inc_section->name) == 0) {
This logic seems very very suspect to me; and likely wrong. For example:

[myrepo]
SigLevel = DatabaseRequired PackageOptional
Server = foobar.com
Include = /path/to/myrepo.override
----> (jump to new file)
Server = example.com
SigLevel = PackageRequred
----> EOF, jump back

You're going to lose my updated siglevel configuration in all of this;
I'm not even sure what is going to happen.

I also don't like the assumption that repos have only "Server" as
their main setting, I have a few plans to add more options to this in
the future and don't want parsing to rely on the fact that right now
only "Server" and "SigLevel" appear there, if possible.

> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* ... still the same one, we'll just import servers */
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * alpm_list_t *i;
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * for(i = inc_section->servers; i; i = alpm_list_next(i)) {
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * section->servers = alpm_list_add(section->servers, i->data);
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * alpm_list_free(inc_section->servers);
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * free(inc_section->name);
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * } else {
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* ... a different one, so let's "finish" it */
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * finish_section(inc_section, parse_options);
> + * * * * * * * * * * * * * * * * * * * * * * * * * * * }
> + * * * * * * * * * * * * * * * * * * * * * * * }
> * * * * * * * * * * * * * * * * * * * *}
> * * * * * * * * * * * * * * * *break;
> * * * * * * * * * * * *}
> --
> 1.7.8.3

jjacky 01-11-2012 10:55 PM

Fix parsing included files w/ sections
 
On 01/11/12 23:00, Dan McGee wrote:
> On Wed, Jan 11, 2012 at 12:52 PM, Olivier Brunel
> <i.am.jack.mail@gmail.com> wrote:
>> When parsing Include directives, a new section_t is now
>> used, to ensure it won't "mess" with the current one (since
>> included files can define new sections, which would result
>> in an invalid "change" of the current section) This new
>> section starts "in" the current one (so included files are
>> parsed as expected, and don't need to open any section);
>> IOW sections propagate down the include chain, not back up.
>>
>> This also solves the bug (?) when two repos with the same name are declared,
>> which could happen in the same file or, more likely, through Include-s.
>> Now only one db will be registered, with all servers in it (it used to
>> be as many dbs with the same name as there were sections).
>
> IOW? bug (?)? "quotes" around "random" words? I know I'm nitpicking,
> but this is not always the most readable English, especially to
> non-native speakers (even I had to look up what IOW was).
>
> Imagine coming back to a commit message in two years- if there is
> anything in it that wouldn't make sense, you need to reword/rewrite
> it. That is the purpose of commit messages.

Noted, sorry. (To be honest I am very new at all this, so I probably
lack proper habits/methodologies. I'll do my best to improve this.)

>
>> Signed-off-by: Olivier Brunel <i.am.jack.mail@gmail.com>
>> ---
>> src/pacman/conf.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++------
>> 1 files changed, 47 insertions(+), 7 deletions(-)
>>
>> diff --git a/src/pacman/conf.c b/src/pacman/conf.c
>> index 2ff16d2..eb3374e 100644
>> --- a/src/pacman/conf.c
>> +++ b/src/pacman/conf.c
>> @@ -628,6 +628,18 @@ struct section_t {
>> alpm_list_t *servers;
>> };
>>
>> +static alpm_db_t *get_db(const char *dbname)
>> +{
>> + alpm_list_t *i;
>> + for(i = alpm_option_get_syncdbs(config->handle); i; i = i->next) {
>> + alpm_db_t *db = i->data;
>> + if(strcmp(alpm_db_get_name(db), dbname) == 0) {
>> + return db;
>> + }
>> + }
>> + return NULL;
>> +}
> Rather than copying this straight out of src/pacman/sync.c, why don't
> you make it visible to the entire compilation unit in util.c/util.h
> (this file) and remove the now unneeded version from sync.c? (for a
> more public function, a longer name might be nice too; something like
> 'get_sync_db' just to be as clear as possible).
>
>> +
>> /**
>> * Wrap up a section once we have reached the end of it. This should be called
>> * when a subsequent section is encountered, or when we have reached the end of
>> @@ -650,13 +662,17 @@ static int finish_section(struct section_t *section, int parse_options)
>> goto cleanup;
>> }
>>
>> - /* if we are not looking at options sections only, register a db */
>> - db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
>> + /* if we are not looking at options sections only, get the db */
>> + db = get_db(section->name);
>> if(db == NULL) {
>> - pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
>> - section->name, alpm_strerror(alpm_errno(config->handle)));
>> - ret = 1;
>> - goto cleanup;
>> + /* not registered yet, let's do it */
> The "let's do it" part is not really necessary; I say this because we
> also try to avoid contractions if possible.
>
>> + db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
>> + if(db == NULL) {
>> + pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
>> + section->name, alpm_strerror(alpm_errno(config->handle)));
>> + ret = 1;
>> + goto cleanup;
>> + }
>> }
>>
>> for(i = section->servers; i; i = alpm_list_next(i)) {
>> @@ -780,6 +796,7 @@ static int _parseconfig(const char *file, struct section_t *section,
>> glob_t globbuf;
>> int globret;
>> size_t gindex;
>> + struct section_t inc_section;
>>
>> if(value == NULL) {
>> pm_printf(ALPM_LOG_ERROR, _("config file %s, line %d: directive '%s' needs a value
"),
>> @@ -816,10 +833,33 @@ static int _parseconfig(const char *file, struct section_t *section,
>> file, linenum, value);
>> break;
>> default:
>> + /* create new section_t for the includes -- to keep ours unaffected */
>> for(gindex = 0; gindex < globbuf.gl_pathc; gindex++) {
>> + /* we use a different section_t for includes, so they can't mess up
>> + * the current one. This section starts "in" the current section ofc */
> ofc?
>
>> + inc_section->name = strdup (section->name);
>> + inc_section->is_options = section->is_options;
>> + inc_section->siglevel = section->siglevel;
>> + inc_section->servers = NULL;
>> pm_printf(ALPM_LOG_DEBUG, "config file %s, line %d: including %s
",
>> file, linenum, globbuf.gl_pathv[gindex]);
>> - _parseconfig(globbuf.gl_pathv[gindex], section, parse_options, depth + 1);
>> + _parseconfig(globbuf.gl_pathv[gindex], inc_section, parse_options, depth + 1);
>> + /* now, if this is a repo ... */
>> + if(!parse_options && !section->is_options) {
>> + if (section->siglevel == inc_section->siglevel
>> + && strcmp(section->name, inc_section->name) == 0) {
> This logic seems very very suspect to me; and likely wrong. For example:
>
> [myrepo]
> SigLevel = DatabaseRequired PackageOptional
> Server = foobar.com
> Include = /path/to/myrepo.override
> ----> (jump to new file)
> Server = example.com
> SigLevel = PackageRequred
> ----> EOF, jump back
>
> You're going to lose my updated siglevel configuration in all of this;
> I'm not even sure what is going to happen.
>
> I also don't like the assumption that repos have only "Server" as
> their main setting, I have a few plans to add more options to this in
> the future and don't want parsing to rely on the fact that right now
> only "Server" and "SigLevel" appear there, if possible.

Right. This was to go with the idea that changes should only go down,
not up. Right now since the same section_t is used, they go both ways
indeed, but that can lead to troubles when defining sections in included
files.

Thing is, supporting it (sections in included files) means that you
could have e.g. this:

[myrepo]
SigLevel = DatabaseRequired PackageOptional
Server = foobar.com
Include = /path/to/myrepo.override
----> (jump to new file)
[anotherrepo]
Server = foo.com
[myrepo]
Server = example.com
SigLevel = PackageRequred
----> EOF, jump back

With the patch, the updated siglevel would indeed not be applied.
Currently, pacman would register two dbs by the name "myrepo" -- is that
how it is supposed to work?
Or should everything be remembered until all files have been parsed, and
only then dbs be registered?

-j

>> + /* ... still the same one, we'll just import servers */
>> + alpm_list_t *i;
>> + for(i = inc_section->servers; i; i = alpm_list_next(i)) {
>> + section->servers = alpm_list_add(section->servers, i->data);
>> + }
>> + alpm_list_free(inc_section->servers);
>> + free(inc_section->name);
>> + } else {
>> + /* ... a different one, so let's "finish" it */
>> + finish_section(inc_section, parse_options);
>> + }
>> + }
>> }
>> break;
>> }
>> --
>> 1.7.8.3
>


All times are GMT. The time now is 06:16 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.