I'm writing hooks to solve infamous kernel problem. Having version in hook 
isn't necessary,
but will save me lot of work (and lot of time at each hook run).


>Воскресенье,  4 сентября 2016, 17:40 UTC от Dave Reisner <[email protected]>:
>
>On Sun, Sep 04, 2016 at 08:36:39PM +0000, Sergey Petrenko via pacman-dev wrote:
>> ---
>
>Missing seems to be some rationale for this patch. What's the problem
>you're interested in solving with this feature?
>
>>  lib/libalpm/hook.c                        | 102 
>> ++++++++++++++++++++----------
>>  test/pacman/tests/TESTS                   |   1 +
>>  test/pacman/tests/hook-target-versions.py |  47 ++++++++++++++
>>  3 files changed, 118 insertions(+), 32 deletions(-)
>>  create mode 100644 test/pacman/tests/hook-target-versions.py
>> 
>> diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c
>> index ccde225..cc6c8bd 100644
>> --- a/lib/libalpm/hook.c
>> +++ b/lib/libalpm/hook.c
>> @@ -55,7 +55,7 @@ struct _alpm_hook_t {
>>      char **cmd;
>>      alpm_list_t *matches;
>>      alpm_hook_when_t when;
>> -    int abort_on_fail, needs_targets;
>> +    int abort_on_fail, needs_targets, needs_versions;
>>  };
>> 
>>  struct _alpm_hook_cb_ctx {
>> @@ -90,7 +90,7 @@ static void _alpm_hook_free(struct _alpm_hook_t *hook)
>>              _alpm_wordsplit_free(hook->cmd);
>>              alpm_list_free_inner(hook->triggers, (alpm_list_fn_free) 
>> _alpm_trigger_free);
>>              alpm_list_free(hook->triggers);
>> -            alpm_list_free(hook->matches);
>> +            alpm_list_free_inner(hook->matches, free);
>>              FREELIST(hook->depends);
>>              free(hook);
>>      }
>> @@ -329,8 +329,11 @@ static int _alpm_hook_parse_cb(const char *file, int 
>> line,
>>                      hook->abort_on_fail = 1;
>>              } else if(strcmp(key, "NeedsTargets") == 0) {
>>                      hook->needs_targets = 1;
>> +            } else if(strcmp(key, "NeedsVersions") == 0) {
>> +                    hook->needs_versions = 1;
>>              } else if(strcmp(key, "Exec") == 0) {
>> -                    if((hook->cmd = _alpm_wordsplit(value)) == NULL) {
>> +                    if((hook->
>> +                            cmd = _alpm_wordsplit(value)) == NULL) {
>>                              if(errno == EINVAL) {
>>                                      error(_("hook %s line %d: invalid value 
>> %s\n"), file, line, value);
>>                              } else {
>> @@ -456,31 +459,53 @@ static int _alpm_hook_trigger_match_file(alpm_handle_t 
>> *handle,
>>  static int _alpm_hook_trigger_match_pkg(alpm_handle_t *handle,
>>              struct _alpm_hook_t *hook, struct _alpm_trigger_t *t)
>>  {
>> -    alpm_list_t *install = NULL, *upgrade = NULL, *remove = NULL;
>> +    alpm_list_t *add = NULL, *remove = NULL;
>> 
>>      if(t->op & ALPM_HOOK_OP_INSTALL || t->op & ALPM_HOOK_OP_UPGRADE) {
>>              alpm_list_t *i;
>>              for(i = handle->trans->add; i; i = i->next) {
>>                      alpm_pkg_t *pkg = i->data;
>> -                    if(_alpm_fnmatch_patterns(t->targets, pkg->name) == 0) {
>> -                            if(pkg->oldpkg) {
>> -                                    if(t->op & ALPM_HOOK_OP_UPGRADE) {
>> -                                            if(hook->needs_targets) {
>> -                                                    upgrade = 
>> alpm_list_add(upgrade, pkg->name);
>> -                                            } else {
>> -                                                    return 1;
>> -                                            }
>> -                                    }
>> -                            } else {
>> -                                    if(t->op & ALPM_HOOK_OP_INSTALL) {
>> -                                            if(hook->needs_targets) {
>> -                                                    install = 
>> alpm_list_add(install, pkg->name);
>> -                                            } else {
>> -                                                    return 1;
>> -                                            }
>> -                                    }
>> +
>> +                    if(_alpm_fnmatch_patterns(t->targets, pkg->name) != 0) {
>> +                            continue;
>> +                    }
>> +
>> +                    int upgrade_match = 0, install_match = 0;
>> +                    if (pkg->oldpkg) {
>> +                            upgrade_match = (t->op & ALPM_HOOK_OP_UPGRADE);
>> +                    } else {
>> +                            install_match = (t->op & ALPM_HOOK_OP_INSTALL);
>> +                    }
>> +
>> +                    if (!upgrade_match && !install_match) {
>> +                            continue;
>> +                    }
>> +
>> +                    if (!hook->needs_targets) {
>> +                            return 1;
>> +                    }
>> +
>> +                    char* output = NULL;
>> +                    size_t len = strlen(pkg->name) + 1;
>> +                    if (hook->needs_versions) {
>> +                            if (upgrade_match) {
>> +                                    len += strlen(pkg->oldpkg->version) + 1;
>>                              }
>> +                            len += strlen(pkg->version) + 1;
>>                      }
>> +                    CALLOC(output, len, sizeof(char), continue);
>> +
>> +                    strcat(output, pkg->name);
>> +                    if (hook->needs_versions) {
>> +                            if (upgrade_match) {
>> +                                    strcat(output, " ");
>> +                                    strcat(output, pkg->oldpkg->version);
>> +                            }
>> +                            strcat(output, " ");
>> +                            strcat(output, pkg->version);
>> +                    }
>> +
>> +                    add = alpm_list_add(add, output);
>>              }
>>      }
>> 
>> @@ -488,25 +513,38 @@ static int _alpm_hook_trigger_match_pkg(alpm_handle_t 
>> *handle,
>>              alpm_list_t *i;
>>              for(i = handle->trans->remove; i; i = i->next) {
>>                      alpm_pkg_t *pkg = i->data;
>> -                    if(pkg && _alpm_fnmatch_patterns(t->targets, pkg->name) 
>> == 0) {
>> -                            if(!alpm_list_find(handle->trans->add, pkg, 
>> _alpm_pkg_cmp)) {
>> -                                    if(hook->needs_targets) {
>> -                                            remove = alpm_list_add(remove, 
>> pkg->name);
>> -                                    } else {
>> -                                            return 1;
>> -                                    }
>> -                            }
>> +
>> +                    if(_alpm_fnmatch_patterns(t->targets, pkg->name) != 0) {
>> +                            continue;
>>                      }
>> +
>> +                    if (!hook->needs_targets) {
>> +                            return 1;
>> +                    }
>> +
>> +                    char* output = NULL;
>> +                    size_t len = strlen(pkg->name) + 1;
>> +                    if (hook->needs_versions) {
>> +                            len += strlen(pkg->version) + 1;
>> +                    }
>> +                    CALLOC(output, len, sizeof(char), continue);
>> +
>> +                    strcat(output, pkg->name);
>> +                    if (hook->needs_versions) {
>> +                            strcat(output, " ");
>> +                            strcat(output, pkg->version);
>> +                    }
>> +
>> +                    remove = alpm_list_add(remove, output);
>>              }
>>      }
>> 
>>      /* if we reached this point we either need the target lists or we didn't
>>       * match anything and the following calls will all be no-ops */
>> -    hook->matches = alpm_list_join(hook->matches, install);
>> -    hook->matches = alpm_list_join(hook->matches, upgrade);
>> +    hook->matches = alpm_list_join(hook->matches, add);
>>      hook->matches = alpm_list_join(hook->matches, remove);
>> 
>> -    return install || upgrade || remove;
>> +    return add || remove;
>>  }
>> 
>>  static int _alpm_hook_trigger_match(alpm_handle_t *handle,
>> diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS
>> index bd5a0b6..9443e90 100644
>> --- a/test/pacman/tests/TESTS
>> +++ b/test/pacman/tests/TESTS
>> @@ -63,6 +63,7 @@ TESTS += 
>> test/pacman/tests/hook-pkg-postinstall-trigger-match.py
>>  TESTS += test/pacman/tests/hook-pkg-remove-trigger-match.py
>>  TESTS += test/pacman/tests/hook-pkg-upgrade-trigger-match.py
>>  TESTS += test/pacman/tests/hook-target-list.py
>> +TESTS += test/pacman/tests/hook-target-versions.py
>>  TESTS += test/pacman/tests/hook-upgrade-trigger-no-match.py
>>  TESTS += test/pacman/tests/ignore001.py
>>  TESTS += test/pacman/tests/ignore002.py
>> diff --git a/test/pacman/tests/hook-target-versions.py 
>> b/test/pacman/tests/hook-target-versions.py
>> new file mode 100644
>> index 0000000..fd6d207
>> --- /dev/null
>> +++ b/test/pacman/tests/hook-target-versions.py
>> @@ -0,0 +1,47 @@
>> +self.description = "Hook with NeedsTargets"
>> +
>> +self.add_hook("hook",
>> +        """
>> +        [Trigger]
>> +        Type = Package
>> +        Operation = Upgrade
>> +        Target = foo
>> +
>> +        # duplicate trigger to check that duplicate targets are removed
>> +        [Trigger]
>> +        Type = Package
>> +        Operation = Install
>> +        Target = bar
>> +
>> +        [Trigger]
>> +        Type = File
>> +        Operation = Install
>> +        # matches files in 'file/' but not 'file/' itself
>> +        Target = somewhere/?*
>> +
>> +        [Action]
>> +        When = PreTransaction
>> +        Exec = bin/sh -c 'while read -r tgt; do printf "%s\\n" "$tgt"; done 
>> > var/log/hook-output'
>> +        NeedsTargets
>> +        NeedsVersions
>> +        """);
>> +
>> +lp1 = pmpkg("foo")
>> +lp1.files = ["file/foo"]
>> +self.addpkg2db("local", lp1)
>> +
>> +p1 = pmpkg("foo", "2.0-1")
>> +p1.files = ["file/foo"]
>> +self.addpkg(p1)
>> +
>> +p2 = pmpkg("bar")
>> +p2.files = ["file/bar"]
>> +self.addpkg(p2)
>> +
>> +self.args = "-U %s %s" % (p1.filename(), p2.filename())
>> +
>> +self.addrule("PACMAN_RETCODE=0")
>> +self.addrule("PKG_EXIST=foo")
>> +self.addrule("""FILE_CONTENTS=var/log/hook-output|bar 1.0-1
>> +foo 1.0-1 2.0-1
>> +""")
>> -- 
>> 2.9.3


-- 
With wish of constant improvement
and unstoppable creativity.
Sergey Petrenko

Reply via email to