git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 3/4] hook: add list command

From
PWPhillip Wood <phillip.wood123@gmail.com>
Date
Aug 17, 2020, 13:36 UTC
Message-ID
<3fda8c55-1373-03a8-9cc1-484345e7fa3e@gmail.com>
In-Reply-To
<20200609214926.GD148632@google.com>
Hi Emily
sorry it has taken me so long to reply
On 09/06/2020 22:49, Emily Shaffer wrote:
Show 38 quoted lines
> On Fri, May 22, 2020 at 11:27:44AM +0100, Phillip Wood wrote:
>>
>> Hi Emily
>>
>> On 21/05/2020 19:54, Emily Shaffer wrote:
>>> [...]
>>> +static int hook_config_lookup(const char *key, const char *value, void *hook_key_cb)
>>> +{
>>> +	const char *hook_key = hook_key_cb;
>>> +
>>> +	if (!strcmp(key, hook_key)) {
>>> +		const char *command = value;
>>> +		struct strbuf hookcmd_name = STRBUF_INIT;
>>> +		struct list_head *pos = NULL, *tmp = NULL;
>>> +
>>> +		/* Check if a hookcmd with that name exists. */
>>> +		strbuf_addf(&hookcmd_name, "hookcmd.%s.command", command);
>>> +		git_config_get_value(hookcmd_name.buf, &command);
>>
>> This looks dodgy to me. This code is called by git_config() as it parses
>> the config files, so it has not had a chance to fully populate the
>> config cache used by git_config_get_value(). I think the test below
>> passes because the hookcmd setting is set in the global file and the
>> hook setting is set in the local file so when we have already parsed the
>> hookcmd setting when we come to look it up. The same comment applies to
>> the hypothetical ordering config mentioned below. I think it would be
>> better to collect the list of hook.<event>.command settings in this
>> callback and then look up any hookcmd settings for those hook commands
>> after we've finished reading all of the config files.
> 
> git_config_get_value() calls repo_read_config(the_repository) if the
> config hasn't been fully parsed yet, so I think what you're worrying
> about is not an issue. It's ugly, I agree, but since the new hotness
> (git_config_get_value() and friends) doesn't offer the same
> functionality as the old solution (config origin) this seemed like an
> okay approach. As I understand it, moving this hookcmd lookup section
> outside of the config callback will save us up to one additional pass
> through the configs, at the expense of a more convoluted code path.

Oh I didn't realize that, thanks for explaining it. Below you mention showing the origin for hookcmds as well as the origin of the command which would mean having to change this code anyway I think.

Show 90 quoted lines
>>
>>> +
>>> +		if (!command)
>>> +			BUG("git_config_get_value overwrote a string it shouldn't have");
>>> +
>>> +		/*
>>> +		 * TODO: implement an option-getting callback, e.g.
>>> +		 *   get configs by pattern hookcmd.$value.*
>>> +		 *   for each key+value, do_callback(key, value, cb_data)
>>> +		 */
>>> +
>>> +		list_for_each_safe(pos, tmp, &hook_head) {
>>> +			struct hook *hook = list_entry(pos, struct hook, list);
>>> +			/*
>>> +			 * The list of hooks to run can be reordered by being redeclared
>>> +			 * in the config. Options about hook ordering should be checked
>>> +			 * here.
>>> +			 */
>>> +			if (0 == strcmp(hook->command.buf, command))
>>> +				remove_hook(pos);
>>> +		}
>>> +		emplace_hook(pos, command);
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +struct list_head* hook_list(const struct strbuf* hookname)
>>> +{
>>> +	struct strbuf hook_key = STRBUF_INIT;
>>> +
>>> +	if (!hookname)
>>> +		return NULL;
>>> +
>>> +	strbuf_addf(&hook_key, "hook.%s.command", hookname->buf);
>>> +
>>> +	git_config(hook_config_lookup, (void*)hook_key.buf);
>>> +
>>> +	return &hook_head;
>>> +}
>>> diff --git a/hook.h b/hook.h
>>> new file mode 100644
>>> index 0000000000..aaf6511cff
>>> --- /dev/null
>>> +++ b/hook.h
>>> @@ -0,0 +1,15 @@
>>> +#include "config.h"
>>> +#include "list.h"
>>> +#include "strbuf.h"
>>> +
>>> +struct hook
>>> +{
>>> +	struct list_head list;
>>> +	enum config_scope origin;
>>> +	struct strbuf command;
>>> +};
>>> +
>>> +struct list_head* hook_list(const struct strbuf *hookname);
>>> +
>>> +void free_hook(struct hook *ptr);
>>> +void clear_hook_list(void);
>>> diff --git a/t/t1360-config-based-hooks.sh b/t/t1360-config-based-hooks.sh
>>> index 34b0df5216..4e46d7dd4e 100755
>>> --- a/t/t1360-config-based-hooks.sh
>>> +++ b/t/t1360-config-based-hooks.sh
>>> @@ -4,8 +4,55 @@ test_description='config-managed multihooks, including git-hook command'
>>>   
>>>   . ./test-lib.sh
>>>   
>>> -test_expect_success 'git hook command does not crash' '
>>> -	git hook
>>> +test_expect_success 'git hook rejects commands without a mode' '
>>> +	test_must_fail git hook pre-commit
>>> +'
>>> +
>>> +
>>> +test_expect_success 'git hook rejects commands without a hookname' '
>>> +	test_must_fail git hook list
>>> +'
>>> +
>>> +test_expect_success 'setup hooks in global, and local' '
>>> +	git config --add --local hook.pre-commit.command "/path/ghi" &&
>>
>> Can I make a plea for the use of test_config please. Writing tests which
>> rely on previous tests for their set-up creates a chain of hidden
>> dependencies that make it hard to add/alter tests later or run a subset
>> of the tests when developing a new patch. t3404-rebase-interactive.sh is
>> a prime example of this and I dread touching it.
> 
> Sure. I'll redo them.
That's great, thanks
Best Wishes
Phillip
Show 34 quoted lines
>>
>>> +	git config --add --global hook.pre-commit.command "/path/def"
>>> +'
>>> +
>>> +test_expect_success 'git hook list orders by config order' '
>>> +	cat >expected <<-\EOF &&
>>> +	global:	/path/def
>>> +	local:	/path/ghi
>>> +	EOF
>>> +
>>> +	git hook list pre-commit >actual &&
>>> +	test_cmp expected actual
>>> +'
>>> +
>>> +test_expect_success 'git hook list dereferences a hookcmd' '
>>> +	git config --add --local hook.pre-commit.command "abc" &&
>>> +	git config --add --global hookcmd.abc.command "/path/abc" &&
>>> +
>>> +	cat >expected <<-\EOF &&
>>> +	global:	/path/def
>>> +	local:	/path/ghi
>>> +	local:	/path/abc
>>
>> We should make it clear in the documentation that the config origin
>> applies to the hook setting, even though we display the hookcmd command
>> which is set globally here for the last hook.
> 
> One of the suggestions from our UX team last week was to make this list
> output clearer to indicate the origin of the command plus the origin of
> the hookcmd object; I'll try to straighten this out and make sure the
> doc agrees.
> 
>   - Emily
> 
Previous: Emily ShafferNext: Johannes Schindelin
Message 9 of 69 in “propose config-based hooks”
  1. 0/4 propose config-based hooksEmily Shaffer, May 21, 2020
  2. 1/4 doc: propose hooks managed by the configEmily Shaffer, May 21, 2020
  3. Phillip WoodMay 22, 2020
  4. Emily ShafferJun 9, 2020
  5. 2/4 hook: scaffolding for git-hook subcommandEmily Shaffer, May 21, 2020
  6. 3/4 hook: add list commandEmily Shaffer, May 21, 2020
  7. Phillip WoodMay 22, 2020
  8. Emily ShafferJun 9, 2020
  9. Phillip WoodAug 17, 2020
  10. Johannes SchindelinMay 24, 2020
  11. Emily ShafferMay 27, 2020
  12. 4/4 hook: add --porcelain to list commandEmily Shaffer, May 21, 2020
  13. Johannes SchindelinMay 24, 2020
  14. Johannes SchindelinMay 25, 2020
  15. 0/6 propose config-based hooksEmily Shaffer, Jul 28, 2020
  16. 1/6 doc: propose hooks managed by the configEmily Shaffer, Jul 28, 2020
  17. 2/6 hook: scaffolding for git-hook subcommandEmily Shaffer, Jul 28, 2020
  18. 3/6 hook: add list commandEmily Shaffer, Jul 28, 2020
  19. 5/6 parse-options: parse into argv_arrayEmily Shaffer, Jul 28, 2020
  20. Junio C HamanoJul 29, 2020
  21. Junio C HamanoJul 30, 2020
  22. 4/6 hook: add --porcelain to list commandEmily Shaffer, Jul 28, 2020
  23. 6/6 hook: add 'run' subcommandEmily Shaffer, Jul 28, 2020
  24. 0/9 propose config-based hooksEmily Shaffer, Sep 9, 2020
  25. 1/9 doc: propose hooks managed by the configEmily Shaffer, Sep 9, 2020
  26. Jonathan TanSep 23, 2020
  27. Emily ShafferSep 24, 2020
  28. Ævar Arnfjörð BjarmasonOct 7, 2020
  29. Emily ShafferOct 22, 2020
  30. Ævar Arnfjörð BjarmasonOct 23, 2020
  31. Emily ShafferOct 29, 2020
  32. Ævar Arnfjörð BjarmasonOct 29, 2020
  33. 2/9 hook: scaffolding for git-hook subcommandEmily Shaffer, Sep 9, 2020
  34. Jonathan NiederOct 5, 2020
  35. Emily ShafferOct 6, 2020
  36. 3/9 hook: add list commandEmily Shaffer, Sep 9, 2020
  37. Phillip WoodSep 11, 2020
  38. Emily ShafferSep 11, 2020
  39. Jonathan TanSep 23, 2020
  40. Emily ShafferOct 6, 2020
  41. Martin ÅgrenSep 27, 2020
  42. Emily ShafferOct 6, 2020
  43. Jonathan NiederOct 5, 2020
  44. 4/9 hook: add --porcelain to list commandEmily Shaffer, Sep 9, 2020
  45. Josh SteadmonSep 28, 2020
  46. 5/9 parse-options: parse into strvecEmily Shaffer, Sep 9, 2020
  47. Jonathan NiederOct 5, 2020
  48. Junio C HamanoOct 6, 2020
  49. 6/9 hook: add 'run' subcommandEmily Shaffer, Sep 9, 2020
  50. Phillip WoodSep 11, 2020
  51. Josh SteadmonSep 28, 2020
  52. Jonathan NiederOct 5, 2020
  53. Emily ShafferOct 6, 2020
  54. 7/9 hook: replace run-command.h:find_hookEmily Shaffer, Sep 9, 2020
  55. Junio C HamanoSep 9, 2020
  56. Emily ShafferSep 10, 2020
  57. Jonathan TanSep 23, 2020
  58. Jonathan NiederOct 5, 2020
  59. 9/9 run_commit_hook: take strvec instead of varargsEmily Shaffer, Sep 9, 2020
  60. Phillip WoodSep 10, 2020
  61. Phillip WoodSep 11, 2020
  62. 8/9 commit: use config-based hooksEmily Shaffer, Sep 9, 2020
  63. Phillip WoodSep 10, 2020
  64. Junio C HamanoSep 10, 2020
  65. Jonathan TanSep 23, 2020
  66. Emily ShafferOct 5, 2020
  67. Jonathan NiederOct 5, 2020
  68. Emily ShafferOct 6, 2020
  69. Junio C HamanoSep 9, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.