From: Emily Shaffer <emilyshaffer@google.com>
To: git@vger.kernel.org
Cc: "Emily Shaffer" <emilyshaffer@google.com>,
"Jeff King" <peff@peff.net>, "Junio C Hamano" <gitster@pobox.com>,
"James Ramsay" <james@jramsay.com.au>,
"Jonathan Nieder" <jrnieder@gmail.com>,
"brian m. carlson" <sandals@crustytoothpaste.net>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
"Phillip Wood" <phillip.wood123@gmail.com>,
"Josh Steadmon" <steadmon@google.com>,
"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
"Jonathan Tan" <jonathantanmy@google.com>
Subject: [PATCH v9 00/37] propose config-based hooks
Date: Wed, 26 May 2021 17:08:19 -0700 [thread overview]
Message-ID: <20210527000856.695702-1-emilyshaffer@google.com> (raw)
In-Reply-To: <20210311021037.3001235-1-emilyshaffer@google.com>
After much delay and $DAYJOB, here is v9.
- Addressed nits in reviews on v8
- sendemail-validate hook becomes non-parallelized; updated to use
Ævar's updated system_or_die() function
- changed strbuf to char* in hooks_list
- Attempted to do so in run_command's stdout callback, but this made
length protection difficult, so stuck with strbuf there.
- test_i18ncmp -> test_cmp
- Stop doing i18n lego in run_hooks()
- Checked that run_hooks_opt_init() is always separated by a space from
variable decl blocks
- Checked for early returns which may skip run_hooks_opt_clear(); this
resulted in minimizing the scope of run_hooks_opt in most places
- Got rid of native-hooks.txt. It was a nice idea, but not attached to a
large and slow series like this one.
- In traces, log the name of the hook (e.g. "pre-commit") instead of the
name of the executable (e.g. "/home/emily/check-for-debug-strings");
the executable name is tracelogged as part of argv anyways, and we
want to be able to tell which hook was responsible for invoking the
executable in question.
Thanks.
- Emily
Emily Shaffer (37):
doc: propose hooks managed by the config
hook: introduce git-hook subcommand
hook: include hookdir hook in list
hook: teach hook.runHookDir
hook: implement hookcmd.<name>.skip
parse-options: parse into strvec
hook: add 'run' subcommand
hook: introduce hook_exists()
hook: support passing stdin to hooks
run-command: allow stdin for run_processes_parallel
hook: allow parallel hook execution
hook: allow specifying working directory for hooks
run-command: add stdin callback for parallelization
hook: provide stdin by string_list or callback
run-command: allow capturing of collated output
hooks: allow callers to capture output
commit: use config-based hooks
am: convert applypatch hooks to use config
merge: use config-based hooks for post-merge hook
gc: use hook library for pre-auto-gc hook
rebase: teach pre-rebase to use hook.h
read-cache: convert post-index-change hook to use config
receive-pack: convert push-to-checkout hook to hook.h
git-p4: use 'git hook' to run hooks
hooks: convert 'post-checkout' hook to hook library
hook: convert 'post-rewrite' hook to config
transport: convert pre-push hook to use config
reference-transaction: look for hooks in config
receive-pack: convert 'update' hook to hook.h
proc-receive: acquire hook list from hook.h
post-update: use hook.h library
receive-pack: convert receive hooks to hook.h
bugreport: use hook_exists instead of find_hook
git-send-email: use 'git hook run' for 'sendemail-validate'
run-command: stop thinking about hooks
doc: clarify fsmonitor-watchman specification
docs: link githooks and git-hook manpages
.gitignore | 1 +
Documentation/Makefile | 1 +
Documentation/config/hook.txt | 27 +
Documentation/git-hook.txt | 162 ++++++
Documentation/githooks.txt | 77 ++-
Documentation/technical/api-parse-options.txt | 7 +
.../technical/config-based-hooks.txt | 369 +++++++++++++
Makefile | 2 +
builtin.h | 1 +
builtin/am.c | 39 +-
builtin/bugreport.c | 4 +-
builtin/checkout.c | 19 +-
builtin/clone.c | 8 +-
builtin/commit.c | 11 +-
builtin/fetch.c | 1 +
builtin/gc.c | 9 +-
builtin/hook.c | 190 +++++++
builtin/merge.c | 15 +-
builtin/rebase.c | 10 +-
builtin/receive-pack.c | 326 ++++++------
builtin/submodule--helper.c | 2 +-
builtin/worktree.c | 32 +-
command-list.txt | 1 +
commit.c | 22 +-
commit.h | 3 +-
git-p4.py | 67 +--
git-send-email.perl | 26 +-
git.c | 1 +
hook.c | 483 ++++++++++++++++++
hook.h | 139 +++++
parse-options-cb.c | 16 +
parse-options.h | 4 +
read-cache.c | 13 +-
refs.c | 43 +-
reset.c | 17 +-
run-command.c | 156 +++---
run-command.h | 55 +-
sequencer.c | 92 ++--
submodule.c | 1 +
t/helper/test-parse-options.c | 6 +
t/helper/test-run-command.c | 46 +-
t/t0040-parse-options.sh | 27 +
t/t0061-run-command.sh | 37 ++
t/t1360-config-based-hooks.sh | 329 ++++++++++++
t/t1416-ref-transaction-hooks.sh | 12 +-
t/t5411/test-0015-too-many-hooks-error.sh | 47 ++
...3-pre-commit-and-pre-merge-commit-hooks.sh | 17 +-
t/t9001-send-email.sh | 13 +-
transport.c | 58 +--
49 files changed, 2505 insertions(+), 539 deletions(-)
create mode 100644 Documentation/config/hook.txt
create mode 100644 Documentation/git-hook.txt
create mode 100644 Documentation/technical/config-based-hooks.txt
create mode 100644 builtin/hook.c
create mode 100644 hook.c
create mode 100644 hook.h
create mode 100755 t/t1360-config-based-hooks.sh
create mode 100644 t/t5411/test-0015-too-many-hooks-error.sh
1: 85b99369f1 ! 1: d2b7ee8317 doc: propose hooks managed by the config
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Since v6, checked for inconsistencies with implementation and added lots of
+ caveats about whether 'git hook add' and 'git hook edit' will ever materialize.
+
+ Hopefully this reflects reality now; please review accordingly.
+
+ Since v6, checked for inconsistencies with implementation and added lots of
+ caveats about whether 'git hook add' and 'git hook edit' will ever materialize.
+
+ Hopefully this reflects reality now; please review accordingly.
+
+ Since v4, addressed comments from Jonathan Tan about wording. However, I have
+ not addressed AEvar's comments or done a full re-review of this document.
+ I wanted to get the rest of the series out for initial review first.
+
+ - Emily
+
+ Since v4, addressed comments from Jonathan Tan about wording.
+
## Documentation/Makefile ##
@@ Documentation/Makefile: SP_ARTICLES += $(API_DOCS)
TECH_DOCS += MyFirstContribution
2: 1d19f1477c < -: ---------- hook: scaffolding for git-hook subcommand
3: c125c63880 ! 2: 112a809f02 hook: add list command
@@ Metadata
Author: Emily Shaffer <emilyshaffer@google.com>
## Commit message ##
- hook: add list command
+ hook: introduce git-hook subcommand
- Teach 'git hook list <hookname>', which checks the known configs in
+ Add a new subcommand, git-hook, which will be used to ease config-based
+ hook management. This command will handle parsing configs to compose a
+ list of hooks to run for a given event, as well as adding or modifying
+ hook configs in an interactive fashion.
+
+ Start with 'git hook list <hookname>', which checks the known configs in
order to create an ordered list of hooks to run on a given hook event.
Multiple commands can be specified for a given hook by providing
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Since v4, mainly changed to RUN_SETUP_GENTLY so that 'git hook list' can
+ be executed outside of a repo.
+
+ ## .gitignore ##
+@@
+ /git-grep
+ /git-hash-object
+ /git-help
++/git-hook
+ /git-http-backend
+ /git-http-fetch
+ /git-http-push
+
## Documentation/config/hook.txt (new) ##
@@
+hook.<command>.command::
@@ Documentation/config/hook.txt (new)
+ as a command. This can be an executable on your device or a oneliner for
+ your shell. See linkgit:git-hook[1].
- ## Documentation/git-hook.txt ##
-@@ Documentation/git-hook.txt: git-hook - Manage configured hooks
- SYNOPSIS
- --------
- [verse]
--'git hook'
+ ## Documentation/git-hook.txt (new) ##
+@@
++git-hook(1)
++===========
++
++NAME
++----
++git-hook - Manage configured hooks
++
++SYNOPSIS
++--------
++[verse]
+'git hook' list <hook-name>
-
- DESCRIPTION
- -----------
--A placeholder command. Later, you will be able to list, add, and modify hooks
--with this command.
++
++DESCRIPTION
++-----------
+You can list configured hooks with this command. Later, you will be able to run,
+add, and modify hooks with this command.
+
@@ Documentation/git-hook.txt: git-hook - Manage configured hooks
+CONFIGURATION
+-------------
+include::config/hook.txt[]
-
- GIT
- ---
++
++GIT
++---
++Part of the linkgit:git[1] suite
## Makefile ##
@@ Makefile: LIB_OBJS += hash-lookup.o
@@ Makefile: LIB_OBJS += hash-lookup.o
LIB_OBJS += ident.o
LIB_OBJS += json-writer.o
LIB_OBJS += kwset.o
+@@ Makefile: BUILTIN_OBJS += builtin/get-tar-commit-id.o
+ BUILTIN_OBJS += builtin/grep.o
+ BUILTIN_OBJS += builtin/hash-object.o
+ BUILTIN_OBJS += builtin/help.o
++BUILTIN_OBJS += builtin/hook.o
+ BUILTIN_OBJS += builtin/index-pack.o
+ BUILTIN_OBJS += builtin/init-db.o
+ BUILTIN_OBJS += builtin/interpret-trailers.o
- ## builtin/hook.c ##
+ ## builtin.h ##
+@@ builtin.h: int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
+ int cmd_grep(int argc, const char **argv, const char *prefix);
+ int cmd_hash_object(int argc, const char **argv, const char *prefix);
+ int cmd_help(int argc, const char **argv, const char *prefix);
++int cmd_hook(int argc, const char **argv, const char *prefix);
+ int cmd_index_pack(int argc, const char **argv, const char *prefix);
+ int cmd_init_db(int argc, const char **argv, const char *prefix);
+ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix);
+
+ ## builtin/hook.c (new) ##
@@
- #include "cache.h"
--
- #include "builtin.h"
++#include "cache.h"
++#include "builtin.h"
+#include "config.h"
+#include "hook.h"
- #include "parse-options.h"
++#include "parse-options.h"
+#include "strbuf.h"
-
- static const char * const builtin_hook_usage[] = {
-- N_("git hook"),
++
++static const char * const builtin_hook_usage[] = {
+ N_("git hook list <hookname>"),
- NULL
- };
-
--int cmd_hook(int argc, const char **argv, const char *prefix)
++ NULL
++};
++
+static int list(int argc, const char **argv, const char *prefix)
- {
-- struct option builtin_hook_options[] = {
++{
+ struct list_head *head, *pos;
-+ struct strbuf hookname = STRBUF_INIT;
++ const char *hookname = NULL;
+
+ struct option list_options[] = {
- OPT_END(),
- };
-
-- argc = parse_options(argc, argv, prefix, builtin_hook_options,
++ OPT_END(),
++ };
++
+ argc = parse_options(argc, argv, prefix, list_options,
- builtin_hook_usage, 0);
-
++ builtin_hook_usage, 0);
++
+ if (argc < 1) {
+ usage_msg_opt(_("You must specify a hook event name to list."),
+ builtin_hook_usage, list_options);
+ }
+
-+ strbuf_addstr(&hookname, argv[0]);
++ hookname = argv[0];
+
-+ head = hook_list(&hookname);
++ head = hook_list(hookname);
+
+ if (list_empty(head)) {
+ printf(_("no commands configured for hook '%s'\n"),
-+ hookname.buf);
-+ strbuf_release(&hookname);
++ hookname);
+ return 0;
+ }
+
@@ builtin/hook.c
+ }
+
+ clear_hook_list(head);
-+ strbuf_release(&hookname);
+
- return 0;
- }
++ return 0;
++}
+
+int cmd_hook(int argc, const char **argv, const char *prefix)
+{
@@ builtin/hook.c
+ usage_with_options(builtin_hook_usage, builtin_hook_options);
+}
+ ## command-list.txt ##
+@@ command-list.txt: git-grep mainporcelain info
+ git-gui mainporcelain
+ git-hash-object plumbingmanipulators
+ git-help ancillaryinterrogators complete
++git-hook mainporcelain
+ git-http-backend synchingrepositories
+ git-http-fetch synchelpers
+ git-http-push synchelpers
+
+ ## git.c ##
+@@ git.c: static struct cmd_struct commands[] = {
+ { "grep", cmd_grep, RUN_SETUP_GENTLY },
+ { "hash-object", cmd_hash_object },
+ { "help", cmd_help },
++ { "hook", cmd_hook, RUN_SETUP_GENTLY },
+ { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY | NO_PARSEOPT },
+ { "init", cmd_init_db },
+ { "init-db", cmd_init_db },
+
## hook.c (new) ##
@@
+#include "cache.h"
@@ hook.c (new)
+ return 0;
+}
+
-+struct list_head* hook_list(const struct strbuf* hookname)
++struct list_head* hook_list(const char* hookname)
+{
+ struct strbuf hook_key = STRBUF_INIT;
+ struct list_head *hook_head = xmalloc(sizeof(struct list_head));
@@ hook.c (new)
+ if (!hookname)
+ return NULL;
+
-+ strbuf_addf(&hook_key, "hook.%s.command", hookname->buf);
++ strbuf_addf(&hook_key, "hook.%s.command", hookname);
+
+ git_config(hook_config_lookup, &cb_data);
+
@@ hook.h (new)
+ * Provides a linked list of 'struct hook' detailing commands which should run
+ * in response to the 'hookname' event, in execution order.
+ */
-+struct list_head* hook_list(const struct strbuf *hookname);
++struct list_head* hook_list(const char *hookname);
+
+/* Free memory associated with a 'struct hook' */
+void free_hook(struct hook *ptr);
+/* Empties the list at 'head', calling 'free_hook()' on each entry */
+void clear_hook_list(struct list_head *head);
- ## t/t1360-config-based-hooks.sh ##
-@@ t/t1360-config-based-hooks.sh: test_description='config-managed multihooks, including git-hook command'
-
- . ./test-lib.sh
-
--test_expect_success 'git hook command does not crash' '
-- git hook
+ ## t/t1360-config-based-hooks.sh (new) ##
+@@
++#!/bin/bash
++
++test_description='config-managed multihooks, including git-hook command'
++
++. ./test-lib.sh
++
+ROOT=
+if test_have_prereq MINGW
+then
@@ t/t1360-config-based-hooks.sh: test_description='config-managed multihooks, incl
+
+ git hook list pre-commit >actual &&
+ test_cmp expected actual
- '
-
- test_done
++'
++
++test_done
4: 0b8cd46ff9 ! 3: 3114306368 hook: include hookdir hook in list
@@ builtin/hook.c: static int list(int argc, const char **argv, const char *prefix)
list_for_each(pos, head) {
struct hook *item = list_entry(pos, struct hook, list);
- if (item)
+- printf("%s: %s\n",
+- config_scope_name(item->origin),
+ item = list_entry(pos, struct hook, list);
+ if (item) {
-+ /* Don't translate 'hookdir' - it matches the config */
- printf("%s: %s\n",
-- config_scope_name(item->origin),
++ /*
++ * TRANSLATORS: "<config scope>: <path>". Both fields
++ * should be left untranslated; config scope matches the
++ * output of 'git config --show-scope'. Marked for
++ * translation to provide better RTL support later.
++ */
++ printf(_("%s: %s\n"),
+ (item->from_hookdir
+ ? "hookdir"
+ : config_scope_name(item->origin)),
@@ hook.c: static void append_or_move_hook(struct list_head *head, const char *comm
}
/* re-set the scope so we show where an override was specified */
-@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+@@ hook.c: struct list_head* hook_list(const char* hookname)
git_config(hook_config_lookup, &cb_data);
+ if (have_git_dir()) {
-+ const char *legacy_hook_path = find_hook(hookname->buf);
++ const char *legacy_hook_path = find_hook(hookname);
+
+ /* Unconditionally add legacy hook, but annotate it. */
+ if (legacy_hook_path) {
5: 05c503fbe1 ! 4: 681013c32a hook: teach hook.runHookDir
@@ Commit message
list'. Later on, though, we will pay attention to this enum when running
the hooks.
+
+ ## Notes ##
+ Since v7, tidied up the behavior of the HOOK_UNKNOWN flag and added a test to
+ enforce it - now it matches the design doc much better.
+
+ Also, thanks Jonathan Tan for pointing out that the commit message made no sense
+ and was targeted for a different change. Rewrote the commit message now.
+
+ Plus, added HOOK_ERROR flag per Junio and Jonathan Nieder.
+
+ Newly split into its own commit since v4, and taking place much sooner.
+
+ An unfortunate side effect of adding this support *before* the
+ hook.runHookDir support is that the labels on the list are not clear -
+ because we aren't yet flagging which hooks are from the hookdir versus
+ the config. I suppose we could move the addition of that field to the
+ struct hook up to this patch, but it didn't make a lot of sense to me to
+ do it just for cosmetic purposes.
+
+ Since v7, tidied up the behavior of the HOOK_UNKNOWN flag and added a test to
+ enforce it - now it matches the design doc much better.
+
+ Also, thanks Jonathan Tan for pointing out that the commit message made no sense
+ and was targeted for a different change. Rewrote the commit message now.
+
+ Newly split into its own commit since v4, and taking place much sooner.
+
+ An unfortunate side effect of adding this support *before* the
+ hook.runHookDir support is that the labels on the list are not clear -
+ because we aren't yet flagging which hooks are from the hookdir versus
+ the config. I suppose we could move the addition of that field to the
+ struct hook up to this patch, but it didn't make a lot of sense to me to
+ do it just for cosmetic purposes.
+
## Documentation/config/hook.txt ##
@@ Documentation/config/hook.txt: hookcmd.<name>.command::
A command to execute during a hook for which <name> has been specified
@@ builtin/hook.c: static const char * const builtin_hook_usage[] = {
static int list(int argc, const char **argv, const char *prefix)
{
struct list_head *head, *pos;
- struct strbuf hookname = STRBUF_INIT;
+ const char *hookname = NULL;
+ struct strbuf hookdir_annotation = STRBUF_INIT;
struct option list_options[] = {
OPT_END(),
@@ builtin/hook.c: static int list(int argc, const char **argv, const char *prefix)
- return 0;
- }
-
-+ switch (should_run_hookdir) {
-+ case HOOKDIR_NO:
-+ strbuf_addstr(&hookdir_annotation, _(" (will not run)"));
-+ break;
-+ case HOOKDIR_ERROR:
-+ strbuf_addstr(&hookdir_annotation, _(" (will error and not run)"));
-+ break;
-+ case HOOKDIR_INTERACTIVE:
-+ strbuf_addstr(&hookdir_annotation, _(" (will prompt)"));
-+ break;
-+ case HOOKDIR_WARN:
-+ strbuf_addstr(&hookdir_annotation, _(" (will warn but run)"));
-+ break;
-+ case HOOKDIR_YES:
-+ /*
-+ * The default behavior should agree with
-+ * hook.c:configured_hookdir_opt(). HOOKDIR_UNKNOWN should just
-+ * do the default behavior.
-+ */
-+ case HOOKDIR_UNKNOWN:
-+ default:
-+ break;
-+ }
-+
- list_for_each(pos, head) {
struct hook *item = list_entry(pos, struct hook, list);
item = list_entry(pos, struct hook, list);
if (item) {
- /* Don't translate 'hookdir' - it matches the config */
-- printf("%s: %s\n",
-+ printf("%s: %s%s\n",
- (item->from_hookdir
- ? "hookdir"
- : config_scope_name(item->origin)),
+- /*
+- * TRANSLATORS: "<config scope>: <path>". Both fields
+- * should be left untranslated; config scope matches the
+- * output of 'git config --show-scope'. Marked for
+- * translation to provide better RTL support later.
+- */
+- printf(_("%s: %s\n"),
+- (item->from_hookdir
+- ? "hookdir"
+- : config_scope_name(item->origin)),
- item->command.buf);
-+ item->command.buf,
-+ (item->from_hookdir
-+ ? hookdir_annotation.buf
-+ : ""));
++ if (item->from_hookdir) {
++ /*
++ * TRANSLATORS: do not translate 'hookdir' as
++ * it matches the config setting.
++ */
++ switch (should_run_hookdir) {
++ case HOOKDIR_NO:
++ printf(_("hookdir: %s (will not run)\n"),
++ item->command.buf);
++ break;
++ case HOOKDIR_ERROR:
++ printf(_("hookdir: %s (will error and not run)\n"),
++ item->command.buf);
++ break;
++ case HOOKDIR_INTERACTIVE:
++ printf(_("hookdir: %s (will prompt)\n"),
++ item->command.buf);
++ break;
++ case HOOKDIR_WARN:
++ printf(_("hookdir: %s (will warn but run)\n"),
++ item->command.buf);
++ break;
++ case HOOKDIR_YES:
++ /*
++ * The default behavior should agree with
++ * hook.c:configured_hookdir_opt(). HOOKDIR_UNKNOWN should just
++ * do the default behavior.
++ */
++ case HOOKDIR_UNKNOWN:
++ default:
++ printf(_("hookdir: %s\n"),
++ item->command.buf);
++ break;
++ }
++ } else {
++ /*
++ * TRANSLATORS: "<config scope>: <path>". Both fields
++ * should be left untranslated; config scope matches the
++ * output of 'git config --show-scope'. Marked for
++ * translation to provide better RTL support later.
++ */
++ printf(_("%s: %s\n"),
++ config_scope_name(item->origin),
++ item->command.buf);
++ }
}
}
clear_hook_list(head);
+ strbuf_release(&hookdir_annotation);
- strbuf_release(&hookname);
return 0;
-@@ builtin/hook.c: static int list(int argc, const char **argv, const char *prefix)
+ }
int cmd_hook(int argc, const char **argv, const char *prefix)
{
@@ builtin/hook.c: static int list(int argc, const char **argv, const char *prefix)
+ else if (!strcmp(run_hookdir, "interactive"))
+ should_run_hookdir = HOOKDIR_INTERACTIVE;
+ else
++ /*
++ * TRANSLATORS: leave "yes/warn/interactive/no"
++ * untranslated; the strings are compared literally.
++ */
+ die(_("'%s' is not a valid option for --run-hookdir "
+ "(yes, warn, interactive, no)"), run_hookdir);
+ else
@@ hook.c: static int hook_config_lookup(const char *key, const char *value, void *
+ return HOOKDIR_UNKNOWN;
+}
+
- struct list_head* hook_list(const struct strbuf* hookname)
+ struct list_head* hook_list(const char* hookname)
{
struct strbuf hook_key = STRBUF_INIT;
## hook.h ##
@@ hook.h: struct hook {
*/
- struct list_head* hook_list(const struct strbuf *hookname);
+ struct list_head* hook_list(const char *hookname);
+enum hookdir_opt
+{
@@ hook.h: struct hook {
+ * command line arguments.
+ */
+enum hookdir_opt configured_hookdir_opt(void);
++
++/*
++ * Provides the hookdir_opt specified in the config without consulting any
++ * command line arguments.
++ */
++enum hookdir_opt configured_hookdir_opt(void);
+
/* Free memory associated with a 'struct hook' */
void free_hook(struct hook *ptr);
@@ t/t1360-config-based-hooks.sh: test_expect_success 'git hook list shows hooks fr
+
+ git hook list pre-commit >actual &&
+ # the hookdir annotation is translated
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
+test_expect_success 'hook.runHookDir = error is respected by list' '
@@ t/t1360-config-based-hooks.sh: test_expect_success 'git hook list shows hooks fr
+
+ git hook list pre-commit >actual &&
+ # the hookdir annotation is translated
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
+test_expect_success 'hook.runHookDir = warn is respected by list' '
@@ t/t1360-config-based-hooks.sh: test_expect_success 'git hook list shows hooks fr
+
+ git hook list pre-commit >actual &&
+ # the hookdir annotation is translated
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
+
@@ t/t1360-config-based-hooks.sh: test_expect_success 'git hook list shows hooks fr
+
+ git hook list pre-commit >actual &&
+ # the hookdir annotation is translated
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
+test_expect_success 'hook.runHookDir is tolerant to unknown values' '
@@ t/t1360-config-based-hooks.sh: test_expect_success 'git hook list shows hooks fr
+
+ git hook list pre-commit >actual &&
+ # the hookdir annotation is translated
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
test_done
6: e86025853a ! 5: 0a4b9f27b3 hook: implement hookcmd.<name>.skip
@@ hook.c: static int hook_config_lookup(const char *key, const char *value, void *
## t/t1360-config-based-hooks.sh ##
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = warn is respected by list' '
- test_i18ncmp expected actual
+ test_cmp expected actual
'
+test_expect_success 'git hook list removes skipped hookcmd' '
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = warn is re
+ EOF
+
+ git hook list pre-commit >actual &&
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
+test_expect_success 'git hook list ignores skip referring to unused hookcmd' '
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = warn is re
+ EOF
+
+ git hook list pre-commit >actual &&
-+ test_i18ncmp expected actual
++ test_cmp expected actual
+'
+
+test_expect_success 'git hook list removes skipped inlined hook' '
7: 6e10593d75 ! 6: 2ad4f44d08 parse-options: parse into strvec
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Since v7, updated the reference doc to make the intended usage for OPT_STRVEC
+ more clear.
+
+ Since v4, fixed one or two more places where I missed the argv_array->strvec
+ rename.
+
## Documentation/technical/api-parse-options.txt ##
@@ Documentation/technical/api-parse-options.txt: There are some macros to easily define options:
The string argument is stored as an element in `string_list`.
@@ parse-options.h: int parse_opt_commits(const struct option *, const char *, int)
int parse_opt_noop_cb(const struct option *, const char *, int);
enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
const struct option *,
+
+ ## t/helper/test-parse-options.c ##
+@@
+ #include "cache.h"
+ #include "parse-options.h"
+ #include "string-list.h"
++#include "strvec.h"
+ #include "trace2.h"
+
+ static int boolean = 0;
+@@ t/helper/test-parse-options.c: static char *string = NULL;
+ static char *file = NULL;
+ static int ambiguous;
+ static struct string_list list = STRING_LIST_INIT_NODUP;
++static struct strvec vector = STRVEC_INIT;
+
+ static struct {
+ int called;
+@@ t/helper/test-parse-options.c: int cmd__parse_options(int argc, const char **argv)
+ OPT_STRING('o', NULL, &string, "str", "get another string"),
+ OPT_NOOP_NOARG(0, "obsolete"),
+ OPT_STRING_LIST(0, "list", &list, "str", "add str to list"),
++ OPT_STRVEC(0, "vector", &vector, "str", "add str to strvec"),
+ OPT_GROUP("Magic arguments"),
+ OPT_ARGUMENT("quux", NULL, "means --quux"),
+ OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
+@@ t/helper/test-parse-options.c: int cmd__parse_options(int argc, const char **argv)
+ for (i = 0; i < list.nr; i++)
+ show(&expect, &ret, "list: %s", list.items[i].string);
+
++ for (i = 0; i < vector.nr; i++)
++ show(&expect, &ret, "vector: %s", vector.v[i]);
++
+ for (i = 0; i < argc; i++)
+ show(&expect, &ret, "arg %02d: %s", i, argv[i]);
+
+
+ ## t/t0040-parse-options.sh ##
+@@ t/t0040-parse-options.sh: String options
+ --st <st> get another string (pervert ordering)
+ -o <str> get another string
+ --list <str> add str to list
++ --vector <str> add str to strvec
+
+ Magic arguments
+ --quux means --quux
+@@ t/t0040-parse-options.sh: test_expect_success '--no-list resets list' '
+ test_cmp expect output
+ '
+
++cat >expect <<\EOF
++boolean: 0
++integer: 0
++magnitude: 0
++timestamp: 0
++string: (not set)
++abbrev: 7
++verbose: -1
++quiet: 0
++dry run: no
++file: (not set)
++vector: foo
++vector: bar
++vector: baz
++EOF
++test_expect_success '--vector keeps list of strings' '
++ test-tool parse-options --vector foo --vector=bar --vector=baz >output &&
++ test_cmp expect output
++'
++
++test_expect_success '--no-vector resets list' '
++ test-tool parse-options --vector=other --vector=irrelevant --vector=options \
++ --no-vector --vector=foo --vector=bar --vector=baz >output &&
++ test_cmp expect output
++'
++
+ test_expect_success 'multiple quiet levels' '
+ test-tool parse-options --expect="quiet: 3" -q -q -q
+ '
8: 0dc9284057 ! 7: 27dd8e3edf hook: add 'run' subcommand
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Since v7, added support for "error" hook.runHookDir setting.
+
+ Since v4, updated the docs, and did less local application of single
+ quotes. In order for hookdir hooks to run successfully with a space in
+ the path, though, they must not be run with 'sh -c'. So we can treat the
+ hookdir hooks specially, and warn users via doc about special
+ considerations for configured hooks with spaces in their path.
+
## Documentation/git-hook.txt ##
@@ Documentation/git-hook.txt: SYNOPSIS
--------
@@ hook.c
void free_hook(struct hook *ptr)
{
+- if (ptr) {
++ if (ptr)
+ strbuf_release(&ptr->command);
+- free(ptr);
+- }
++ free(ptr);
+ }
+
+ static struct hook * find_hook_by_command(struct list_head *head, const char *command)
@@ hook.c: enum hookdir_opt configured_hookdir_opt(void)
return HOOKDIR_UNKNOWN;
}
@@ hook.c: enum hookdir_opt configured_hookdir_opt(void)
+
+ switch (cfg)
+ {
-+ case HOOKDIR_ERROR:
-+ fprintf(stderr, _("Skipping legacy hook at '%s'\n"),
-+ path);
-+ /* FALLTHROUGH */
-+ case HOOKDIR_NO:
-+ return 0;
-+ case HOOKDIR_WARN:
-+ fprintf(stderr, _("Running legacy hook at '%s'\n"),
-+ path);
-+ return 1;
-+ case HOOKDIR_INTERACTIVE:
-+ do {
-+ /*
-+ * TRANSLATORS: Make sure to include [Y] and [n]
-+ * in your translation. Only English input is
-+ * accepted. Default option is "yes".
-+ */
-+ fprintf(stderr, _("Run '%s'? [Yn] "), path);
-+ git_read_line_interactively(&prompt);
-+ strbuf_tolower(&prompt);
-+ if (starts_with(prompt.buf, "n")) {
-+ strbuf_release(&prompt);
-+ return 0;
-+ } else if (starts_with(prompt.buf, "y")) {
-+ strbuf_release(&prompt);
-+ return 1;
-+ }
-+ /* otherwise, we didn't understand the input */
-+ } while (prompt.len); /* an empty reply means "Yes" */
-+ strbuf_release(&prompt);
-+ return 1;
-+ /*
-+ * HOOKDIR_UNKNOWN should match the default behavior, but let's
-+ * give a heads up to the user.
-+ */
-+ case HOOKDIR_UNKNOWN:
-+ fprintf(stderr,
-+ _("Unrecognized value for 'hook.runHookDir'. "
-+ "Is there a typo? "));
-+ /* FALLTHROUGH */
-+ case HOOKDIR_YES:
-+ default:
-+ return 1;
++ case HOOKDIR_ERROR:
++ fprintf(stderr, _("Skipping legacy hook at '%s'\n"),
++ path);
++ /* FALLTHROUGH */
++ case HOOKDIR_NO:
++ return 0;
++ case HOOKDIR_WARN:
++ fprintf(stderr, _("Running legacy hook at '%s'\n"),
++ path);
++ return 1;
++ case HOOKDIR_INTERACTIVE:
++ do {
++ /*
++ * TRANSLATORS: Make sure to include [Y] and [n]
++ * in your translation. Only English input is
++ * accepted. Default option is "yes".
++ */
++ fprintf(stderr, _("Run '%s'? [Y/n] "), path);
++ git_read_line_interactively(&prompt);
++ /*
++ * In case of prompt = '' - that is, user hit enter,
++ * saying "yes I want the default" - strncasecmp will
++ * return 0 regardless. So list the default first.
++ *
++ * Case insensitively, accept "y", "ye", or "yes" as
++ * "yes"; accept "n" or "no" as "no".
++ */
++ if (!strncasecmp(prompt.buf, "yes", prompt.len)) {
++ strbuf_release(&prompt);
++ return 1;
++ } else if (!strncasecmp(prompt.buf, "no", prompt.len)) {
++ strbuf_release(&prompt);
++ return 0;
++ }
++ /* otherwise, we didn't understand the input */
++ } while (prompt.len); /* an empty reply means default (yes) */
++ return 1;
++ /*
++ * HOOKDIR_UNKNOWN should match the default behavior, but let's
++ * give a heads up to the user.
++ */
++ case HOOKDIR_UNKNOWN:
++ fprintf(stderr,
++ _("Unrecognized value for 'hook.runHookDir'. "
++ "Is there a typo? "));
++ /* FALLTHROUGH */
++ case HOOKDIR_YES:
++ default:
++ return 1;
+ }
+}
+
- struct list_head* hook_list(const struct strbuf* hookname)
+ struct list_head* hook_list(const char* hookname)
{
struct strbuf hook_key = STRBUF_INIT;
-@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+@@ hook.c: struct list_head* hook_list(const char* hookname)
strbuf_release(&hook_key);
return hook_head;
}
@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+ strvec_clear(&o->args);
+}
+
-+static void prepare_hook_cp(struct hook *hook, struct run_hooks_opt *options,
++static void prepare_hook_cp(const char *hookname, struct hook *hook,
++ struct run_hooks_opt *options,
+ struct child_process *cp)
+{
+ if (!hook)
@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+ cp->no_stdin = 1;
+ cp->env = options->env.v;
+ cp->stdout_to_stderr = 1;
-+ cp->trace2_hook_name = hook->command.buf;
++ cp->trace2_hook_name = hookname;
+
+ /*
+ * Commands from the config could be oneliners, but we know
@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+
+int run_hooks(const char *hookname, struct run_hooks_opt *options)
+{
-+ struct strbuf hookname_str = STRBUF_INIT;
+ struct list_head *to_run, *pos = NULL, *tmp = NULL;
+ int rc = 0;
+
+ if (!options)
+ BUG("a struct run_hooks_opt must be provided to run_hooks");
+
-+ strbuf_addstr(&hookname_str, hookname);
-+
-+ to_run = hook_list(&hookname_str);
++ to_run = hook_list(hookname);
+
+ list_for_each_safe(pos, tmp, to_run) {
+ struct child_process hook_proc = CHILD_PROCESS_INIT;
@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+ !should_include_hookdir(hook->command.buf, options->run_hookdir))
+ continue;
+
-+ prepare_hook_cp(hook, options, &hook_proc);
++ prepare_hook_cp(hookname, hook, options, &hook_proc);
+
+ rc |= run_command(&hook_proc);
+ }
@@ hook.h: enum hookdir_opt
+void run_hooks_opt_init(struct run_hooks_opt *o);
+void run_hooks_opt_clear(struct run_hooks_opt *o);
+
-+/*
+ /*
+- * Provides the hookdir_opt specified in the config without consulting any
+- * command line arguments.
+ * Runs all hooks associated to the 'hookname' event in order. Each hook will be
+ * passed 'env' and 'args'.
-+ */
+ */
+-enum hookdir_opt configured_hookdir_opt(void);
+int run_hooks(const char *hookname, struct run_hooks_opt *options);
-+
+
/* Free memory associated with a 'struct hook' */
void free_hook(struct hook *ptr);
- /* Empties the list at 'head', calling 'free_hook()' on each entry */
## t/t1360-config-based-hooks.sh ##
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = no is respected by list' '
git hook list pre-commit >actual &&
# the hookdir annotation is translated
-- test_i18ncmp expected actual
-+ test_i18ncmp expected actual &&
+- test_cmp expected actual
++ test_cmp expected actual &&
+
+ git hook run pre-commit 2>actual &&
+ test_must_be_empty actual
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = error is r
git hook list pre-commit >actual &&
# the hookdir annotation is translated
-+ test_i18ncmp expected actual &&
++ test_cmp expected actual &&
+
+ cat >expected <<-EOF &&
+ Skipping legacy hook at '\''$(pwd)/.git/hooks/pre-commit'\''
+ EOF
+
+ git hook run pre-commit 2>actual &&
- test_i18ncmp expected actual
+ test_cmp expected actual
'
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = warn is respected by list' '
git hook list pre-commit >actual &&
# the hookdir annotation is translated
-+ test_i18ncmp expected actual &&
++ test_cmp expected actual &&
+
+ cat >expected <<-EOF &&
+ Running legacy hook at '\''$(pwd)/.git/hooks/pre-commit'\''
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = warn is re
+ EOF
+
+ git hook run pre-commit 2>actual &&
- test_i18ncmp expected actual
+ test_cmp expected actual
'
@@ t/t1360-config-based-hooks.sh: test_expect_success 'git hook list removes skipped inlined hook' '
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = interactiv
git hook list pre-commit >actual &&
# the hookdir annotation is translated
-- test_i18ncmp expected actual
-+ test_i18ncmp expected actual &&
++ test_cmp expected actual &&
+
+ test_write_lines n | git hook run pre-commit 2>actual &&
+ ! grep "Legacy Hook" actual &&
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = interactiv
+ test_cmp expected actual
+'
+
++test_expect_success 'git hook run can pass args and env vars' '
++ write_script sample-hook.sh <<-\EOF &&
++ echo $1
++ echo $2
++ echo $TEST_ENV_1
++ echo $TEST_ENV_2
++ EOF
++
++ test_config hook.pre-commit.command "\"$(pwd)/sample-hook.sh\"" &&
++
++ cat >expected <<-EOF &&
++ arg1
++ arg2
++ env1
++ env2
++ EOF
++
++ git hook run --arg arg1 \
++ --env TEST_ENV_1=env1 \
++ -a arg2 \
++ -e TEST_ENV_2=env2 \
++ pre-commit 2>actual &&
++
+ test_cmp expected actual
+ '
+
+test_expect_success 'hookdir hook included in git hook run' '
+ setup_hookdir &&
+
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir = interactiv
+ setup_hooks &&
+
+ nongit test_must_fail git hook run pre-commit
- '
-
++'
++
test_expect_success 'hook.runHookDir is tolerant to unknown values' '
+ setup_hookdir &&
+
9: 92c67ed9da ! 8: 46975c11c8 hook: introduce hook_exists()
@@ hook.c: void run_hooks_opt_init(struct run_hooks_opt *o)
strvec_clear(&o->env);
## hook.h ##
-@@ hook.h: struct list_head* hook_list(const struct strbuf *hookname);
+@@ hook.h: struct list_head* hook_list(const char *hookname);
enum hookdir_opt
{
10: 9b3bb0b655 ! 9: e11f9e28a3 hook: support passing stdin to hooks
@@ hook.c: void run_hooks_opt_init(struct run_hooks_opt *o)
o->run_hookdir = configured_hookdir_opt();
}
-@@ hook.c: static void prepare_hook_cp(struct hook *hook, struct run_hooks_opt *options,
+@@ hook.c: static void prepare_hook_cp(const char *hookname, struct hook *hook,
if (!hook)
return;
@@ hook.c: static void prepare_hook_cp(struct hook *hook, struct run_hooks_opt *opt
+
cp->env = options->env.v;
cp->stdout_to_stderr = 1;
- cp->trace2_hook_name = hook->command.buf;
+ cp->trace2_hook_name = hookname;
## hook.h ##
@@ hook.h: struct run_hooks_opt
@@ hook.h: int hook_exists(const char *hookname, enum hookdir_opt should_run_hookdi
## t/t1360-config-based-hooks.sh ##
@@ t/t1360-config-based-hooks.sh: test_expect_success 'hook.runHookDir is tolerant to unknown values' '
- test_i18ncmp expected actual
+ test_cmp expected actual
'
+test_expect_success 'stdin to multiple hooks' '
11: 9933985e78 = 10: 3ceb4156fd run-command: allow stdin for run_processes_parallel
12: 43caafe656 ! 11: 93a47f5242 hook: allow parallel hook execution
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Per AEvar's request - parallel hook execution on day zero.
+
+ In most ways run_processes_parallel() worked great for me - but it didn't
+ have great support for hooks where we pipe to and from. I had to add this
+ support later in the series.
+
+ Since I modified an existing and in-use library I'd appreciate a keen look on
+ these patches.
+
+ - Emily
+
## Documentation/config/hook.txt ##
@@ Documentation/config/hook.txt: hook.runHookDir::
Controls how hooks contained in your hookdir are executed. Can be any of
@@ hook.c: enum hookdir_opt configured_hookdir_opt(void)
static int should_include_hookdir(const char *path, enum hookdir_opt cfg)
{
struct strbuf prompt = STRBUF_INIT;
-@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+@@ hook.c: struct list_head* hook_list(const char* hookname)
return hook_head;
}
@@ hook.c: void run_hooks_opt_clear(struct run_hooks_opt *o)
strvec_clear(&o->args);
}
--static void prepare_hook_cp(struct hook *hook, struct run_hooks_opt *options,
+-static void prepare_hook_cp(const char *hookname, struct hook *hook,
+- struct run_hooks_opt *options,
- struct child_process *cp)
+static int pick_next_hook(struct child_process *cp,
+ struct strbuf *out,
@@ hook.c: void run_hooks_opt_clear(struct run_hooks_opt *o)
- cp->env = options->env.v;
+ cp->env = hook_cb->options->env.v;
cp->stdout_to_stderr = 1;
- cp->trace2_hook_name = hook->command.buf;
+- cp->trace2_hook_name = hookname;
++ cp->trace2_hook_name = hook_cb->hookname;
-@@ hook.c: static void prepare_hook_cp(struct hook *hook, struct run_hooks_opt *options,
+ /*
+ * Commands from the config could be oneliners, but we know
+@@ hook.c: static void prepare_hook_cp(const char *hookname, struct hook *hook,
* add passed-in argv, without expanding - let the user get back
* exactly what they put in
*/
@@ hook.c: static void prepare_hook_cp(struct hook *hook, struct run_hooks_opt *opt
int run_hooks(const char *hookname, struct run_hooks_opt *options)
{
- struct strbuf hookname_str = STRBUF_INIT;
struct list_head *to_run, *pos = NULL, *tmp = NULL;
- int rc = 0;
-+ struct hook_cb_data cb_data = { 0, NULL, NULL, options };
++ struct hook_cb_data cb_data = { 0, hookname, NULL, NULL, options };
if (!options)
BUG("a struct run_hooks_opt must be provided to run_hooks");
@@ hook.c: int run_hooks(const char *hookname, struct run_hooks_opt *options)
- to_run = hook_list(&hookname_str);
+ to_run = hook_list(hookname);
list_for_each_safe(pos, tmp, to_run) {
- struct child_process hook_proc = CHILD_PROCESS_INIT;
@@ hook.c: int run_hooks(const char *hookname, struct run_hooks_opt *options)
+ if (list_empty(to_run))
+ return 0;
-- prepare_hook_cp(hook, options, &hook_proc);
+- prepare_hook_cp(hookname, hook, options, &hook_proc);
+ cb_data.head = to_run;
+ cb_data.run_me = list_entry(to_run->next, struct hook, list);
@@ hook.h: struct run_hooks_opt
+ */
+struct hook_cb_data {
+ int rc;
++ const char *hookname;
+ struct list_head *head;
+ struct hook *run_me;
+ struct run_hooks_opt *options;
13: 2e189a7566 ! 12: 7f8c886d3f hook: allow specifying working directory for hooks
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Needed later for "post-checkout" conversion.
+
## hook.c ##
@@ hook.c: void run_hooks_opt_init_sync(struct run_hooks_opt *o)
o->path_to_stdin = NULL;
@@ hook.c: void run_hooks_opt_init_sync(struct run_hooks_opt *o)
@@ hook.c: static int pick_next_hook(struct child_process *cp,
cp->env = hook_cb->options->env.v;
cp->stdout_to_stderr = 1;
- cp->trace2_hook_name = hook->command.buf;
+ cp->trace2_hook_name = hook_cb->hookname;
+ cp->dir = hook_cb->options->dir;
/*
14: 07899ad346 = 13: 8930baa9db run-command: add stdin callback for parallelization
15: d3f18e433f ! 14: d0f362591a hook: provide stdin by string_list or callback
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
## hook.c ##
-@@ hook.c: void free_hook(struct hook *ptr)
+@@
+
+ void free_hook(struct hook *ptr)
{
- if (ptr) {
+- if (ptr)
++ if (ptr) {
strbuf_release(&ptr->command);
+ free(ptr->feed_pipe_cb_data);
- free(ptr);
- }
++ }
+ free(ptr);
}
+
@@ hook.c: static void append_or_move_hook(struct list_head *head, const char *command)
strbuf_init(&to_add->command, 0);
strbuf_addstr(&to_add->command, command);
@@ hook.c: int run_hooks(const char *hookname, struct run_hooks_opt *options)
+ if (options->path_to_stdin && options->feed_pipe)
+ BUG("choose only one method to populate stdin");
+
- strbuf_addstr(&hookname_str, hookname);
+ to_run = hook_list(hookname);
- to_run = hook_list(&hookname_str);
+ list_for_each_safe(pos, tmp, to_run) {
@@ hook.c: int run_hooks(const char *hookname, struct run_hooks_opt *options)
run_processes_parallel_tr2(options->jobs,
pick_next_hook,
16: 417c3f054e ! 15: 83bbb405a5 run-command: allow capturing of collated output
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Originally when writing this patch I attempted to use a pipe in memory -
+ but managing its lifetime was actually pretty tricky, and I found I could
+ achieve the same thing with less code by doing it this way. Critique welcome,
+ including "no, you really need to do it with a pipe".
+
## builtin/fetch.c ##
@@ builtin/fetch.c: static int fetch_multiple(struct string_list *list, int max_children)
result = run_processes_parallel_tr2(max_children,
17: c0f3471bd1 ! 16: 73ed5de54c hooks: allow callers to capture output
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ You can see this in practice in the conversions for some of the push hooks,
+ like 'receive-pack'.
+
## hook.c ##
@@ hook.c: void run_hooks_opt_init_sync(struct run_hooks_opt *o)
o->dir = NULL;
18: 13446e4273 = 17: 900c4d8963 commit: use config-based hooks
19: 9380c43180 ! 18: a562120e22 am: convert applypatch hooks to use config
@@ builtin/am.c: static void am_destroy(const struct am_state *state)
{
int ret;
+ struct run_hooks_opt opt;
++
+ run_hooks_opt_init_sync(&opt);
assert(state->msg);
@@ builtin/am.c: static void do_commit(const struct am_state *state)
const char *reflog_msg, *author, *committer = NULL;
struct strbuf sb = STRBUF_INIT;
+ struct run_hooks_opt hook_opt;
++
+ run_hooks_opt_init_async(&hook_opt);
- if (run_hook_le(NULL, "pre-applypatch", NULL))
-+ if (run_hooks("pre-applypatch", &hook_opt))
++ if (run_hooks("pre-applypatch", &hook_opt)) {
++ run_hooks_opt_clear(&hook_opt);
exit(1);
++ }
++
++ run_hooks_opt_clear(&hook_opt);
if (write_cache_as_tree(&tree, 0, NULL))
+ die(_("git write-tree failed to write a tree"));
@@ builtin/am.c: static void do_commit(const struct am_state *state)
fclose(fp);
}
- run_hook_le(NULL, "post-applypatch", NULL);
++ run_hooks_opt_init_async(&hook_opt);
+ run_hooks("post-applypatch", &hook_opt);
+ run_hooks_opt_clear(&hook_opt);
20: 316a605606 ! 19: e841ed4384 merge: use config-based hooks for post-merge hook
@@ builtin/merge.c: static void finish(struct commit *head_commit,
struct strbuf reflog_message = STRBUF_INIT;
+ struct run_hooks_opt opt;
const struct object_id *head = &head_commit->object.oid;
-+ run_hooks_opt_init_async(&opt);
if (!msg)
- strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
@@ builtin/merge.c: static void finish(struct commit *head_commit,
}
/* Run a post-merge hook */
- run_hook_le(NULL, "post-merge", squash ? "1" : "0", NULL);
++ run_hooks_opt_init_async(&opt);
+ strvec_push(&opt.args, squash ? "1" : "0");
+ run_hooks("post-merge", &opt);
+ run_hooks_opt_clear(&opt);
21: a5132f14b3 ! 20: 7e99398f7d gc: use hook library for pre-auto-gc hook
@@ builtin/gc.c: static void add_repack_incremental_option(void)
static int need_to_gc(void)
{
+ struct run_hooks_opt hook_opt;
-+ run_hooks_opt_init_async(&hook_opt);
++
/*
* Setting gc.auto to 0 or negative can disable the
* automatic gc.
@@ builtin/gc.c: static int need_to_gc(void)
return 0;
- if (run_hook_le(NULL, "pre-auto-gc", NULL))
-+ if (run_hooks("pre-auto-gc", &hook_opt))
++ run_hooks_opt_init_async(&hook_opt);
++ if (run_hooks("pre-auto-gc", &hook_opt)) {
++ run_hooks_opt_clear(&hook_opt);
return 0;
++ }
++ run_hooks_opt_clear(&hook_opt);
return 1;
}
+
22: 01f1331cc9 ! 21: 5423217ef2 rebase: teach pre-rebase to use hook.h
@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix
struct option builtin_rebase_options[] = {
OPT_STRING(0, "onto", &options.onto_name,
N_("revision"),
-@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
- };
- int i;
-
-+ run_hooks_opt_init_async(&hook_opt);
-+
- if (argc == 2 && !strcmp(argv[1], "-h"))
- usage_with_options(builtin_rebase_usage,
- builtin_rebase_options);
@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
}
/* If a hook exists, give it a chance to interrupt*/
++ run_hooks_opt_init_async(&hook_opt);
+ strvec_pushl(&hook_opt.args, options.upstream_arg, argc ? argv[0] : NULL, NULL);
if (!ok_to_skip_pre_rebase &&
- run_hook_le(NULL, "pre-rebase", options.upstream_arg,
- argc ? argv[0] : NULL, NULL))
-+ run_hooks("pre-rebase", &hook_opt))
++ run_hooks("pre-rebase", &hook_opt)) {
++ run_hooks_opt_clear(&hook_opt);
die(_("The pre-rebase hook refused to rebase."));
++ }
++ run_hooks_opt_clear(&hook_opt);
if (options.flags & REBASE_DIFFSTAT) {
-@@ builtin/rebase.c: int cmd_rebase(int argc, const char **argv, const char *prefix)
- ret = !!run_specific_rebase(&options, action);
-
- cleanup:
-+ run_hooks_opt_clear(&hook_opt);
- strbuf_release(&buf);
- strbuf_release(&revisions);
- free(options.head_name);
+ struct diff_options opts;
23: 85a7721adc ! 22: 1c0c5ad129 read-cache: convert post-index-change hook to use config
@@ Documentation/githooks.txt: and "0" meaning they were not.
## read-cache.c ##
@@
- #include "fsmonitor.h"
#include "thread-utils.h"
#include "progress.h"
+ #include "sparse-index.h"
+#include "hook.h"
++>>>>>>> 9524a9d29d (read-cache: convert post-index-change hook to use config)
/* Mask for the name length in ce_flags in the on-disk index */
@@ read-cache.c: static int do_write_locked_index(struct index_state *istate, struct lock_file *l
- unsigned flags)
{
int ret;
+ int was_full = !istate->sparse_index;
+ struct run_hooks_opt hook_opt;
-+ run_hooks_opt_init_async(&hook_opt);
- /*
- * TODO trace2: replace "the_repository" with the actual repo instance
+ ret = convert_to_sparse(istate);
+
@@ read-cache.c: static int do_write_locked_index(struct index_state *istate, struct lock_file *l
else
ret = close_lock_file_gently(lock);
@@ read-cache.c: static int do_write_locked_index(struct index_state *istate, struc
- run_hook_le(NULL, "post-index-change",
- istate->updated_workdir ? "1" : "0",
- istate->updated_skipworktree ? "1" : "0", NULL);
++ run_hooks_opt_init_async(&hook_opt);
+ strvec_pushl(&hook_opt.args,
+ istate->updated_workdir ? "1" : "0",
+ istate->updated_skipworktree ? "1" : "0",
24: 21ec3e1a9d ! 23: 1193e856e6 receive-pack: convert push-to-checkout hook to hook.h
@@ builtin/receive-pack.c: static const char *push_to_checkout(unsigned char *hash,
const char *work_tree)
{
+ struct run_hooks_opt opt;
++
+ run_hooks_opt_init_sync(&opt);
+
strvec_pushf(env, "GIT_WORK_TREE=%s", absolute_path(work_tree));
25: e0405e96ad ! 24: 1817b6851b git-p4: use 'git hook' to run hooks
@@ Commit message
Signed-off-by: Emily Shaffer <emilyshaffer@google.com>
+
+ ## Notes ##
+ Maybe there is a better way to do this - I had a hard time getting this to run
+ locally, and Python is not my forte, so if anybody has a better approach I'd
+ love to just take that patch instead :)
+
+ Since v6, removed the developer debug print statements.... :X
+
+ Maybe there is a better way to do this - I had a hard time getting this to run
+ locally, and Python is not my forte, so if anybody has a better approach I'd
+ love to just take that patch instead :)
+
## git-p4.py ##
@@ git-p4.py: def decode_path(path):
26: c52578e078 ! 25: b3a354e4a8 hooks: convert 'post-checkout' hook to hook library
@@ builtin/checkout.c: struct branch_info {
int changed)
{
- return run_hook_le(NULL, "post-checkout",
-- oid_to_hex(old_commit ? &old_commit->object.oid : &null_oid),
-- oid_to_hex(new_commit ? &new_commit->object.oid : &null_oid),
+- oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),
+- oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
- changed ? "1" : "0", NULL);
+ struct run_hooks_opt opt;
+ int rc;
@@ builtin/checkout.c: struct branch_info {
a commit exists. */
-
+ strvec_pushl(&opt.args,
-+ oid_to_hex(old_commit ? &old_commit->object.oid : &null_oid),
-+ oid_to_hex(new_commit ? &new_commit->object.oid : &null_oid),
++ oid_to_hex(old_commit ? &old_commit->object.oid : null_oid()),
++ oid_to_hex(new_commit ? &new_commit->object.oid : null_oid()),
+ changed ? "1" : "0",
+ NULL);
+ rc = run_hooks("post-checkout", &opt);
@@ builtin/clone.c: static int checkout(int submodule_progress)
struct tree_desc t;
int err = 0;
+ struct run_hooks_opt hook_opt;
-+ run_hooks_opt_init_sync(&hook_opt);
if (option_no_checkout)
return 0;
@@ builtin/clone.c: static int checkout(int submodule_progress)
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
-- err |= run_hook_le(NULL, "post-checkout", oid_to_hex(&null_oid),
+- err |= run_hook_le(NULL, "post-checkout", oid_to_hex(null_oid()),
- oid_to_hex(&oid), "1", NULL);
-+ strvec_pushl(&hook_opt.args, oid_to_hex(&null_oid), oid_to_hex(&oid), "1", NULL);
++ run_hooks_opt_init_sync(&hook_opt);
++ strvec_pushl(&hook_opt.args, oid_to_hex(null_oid()), oid_to_hex(&oid), "1", NULL);
+ err |= run_hooks("post-checkout", &hook_opt);
+ run_hooks_opt_clear(&hook_opt);
@@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam
- cp.argv = NULL;
- cp.trace2_hook_name = "post-checkout";
- strvec_pushl(&cp.args, absolute_path(hook),
-- oid_to_hex(&null_oid),
+- oid_to_hex(null_oid()),
- oid_to_hex(&commit->object.oid),
- "1", NULL);
- ret = run_command(&cp);
- }
+ struct run_hooks_opt opt;
++
+ run_hooks_opt_init_sync(&opt);
+
+ strvec_pushl(&opt.env, "GIT_DIR", "GIT_WORK_TREE", NULL);
+ strvec_pushl(&opt.args,
-+ oid_to_hex(&null_oid),
++ oid_to_hex(null_oid()),
+ oid_to_hex(&commit->object.oid),
+ "1",
+ NULL);
@@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam
strvec_clear(&child_env);
+ ## read-cache.c ##
+@@
+ #include "progress.h"
+ #include "sparse-index.h"
+ #include "hook.h"
+->>>>>>> 9524a9d29d (read-cache: convert post-index-change hook to use config)
+
+ /* Mask for the name length in ce_flags in the on-disk index */
+
+
## reset.c ##
@@
#include "tree-walk.h"
@@ reset.c: int reset_head(struct repository *r, struct object_id *oid, const char
}
- if (run_hook)
- run_hook_le(NULL, "post-checkout",
-- oid_to_hex(orig ? orig : &null_oid),
+- oid_to_hex(orig ? orig : null_oid()),
- oid_to_hex(oid), "1", NULL);
+ if (run_hook) {
+ struct run_hooks_opt opt;
++
+ run_hooks_opt_init_sync(&opt);
+ strvec_pushl(&opt.args,
-+ oid_to_hex(orig ? orig : &null_oid),
++ oid_to_hex(orig ? orig : null_oid()),
+ oid_to_hex(oid),
+ "1",
+ NULL);
27: 316cb6f584 ! 26: 692352f9aa hook: convert 'post-rewrite' hook to config
@@ builtin/am.c: static int run_applypatch_msg_hook(struct am_state *state)
- const char *hook = find_hook("post-rewrite");
+ struct run_hooks_opt opt;
int ret;
-+ run_hooks_opt_init_async(&opt);
- if (!hook)
- return 0;
--
++ run_hooks_opt_init_async(&opt);
+
- strvec_push(&cp.args, hook);
- strvec_push(&cp.args, "rebase");
--
-- cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
-- cp.stdout_to_stderr = 1;
-- cp.trace2_hook_name = "post-rewrite";
+ strvec_push(&opt.args, "rebase");
+ opt.path_to_stdin = am_path(state, "rewritten");
-- ret = run_command(&cp);
+- cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
+- cp.stdout_to_stderr = 1;
+- cp.trace2_hook_name = "post-rewrite";
+ ret = run_hooks("post-rewrite", &opt);
+- ret = run_command(&cp);
+-
- close(cp.in);
+ run_hooks_opt_clear(&opt);
return ret;
@@ sequencer.c: int update_head_with_reflog(const struct commit *old_head,
+ struct string_list to_stdin = STRING_LIST_INIT_DUP;
int code;
- struct strbuf sb = STRBUF_INIT;
-+ run_hooks_opt_init_async(&opt);
- argv[0] = find_hook("post-rewrite");
- if (!argv[0])
- return 0;
-+ strvec_push(&opt.args, "amend");
++ run_hooks_opt_init_async(&opt);
- argv[1] = "amend";
- argv[2] = NULL;
@@ sequencer.c: int update_head_with_reflog(const struct commit *old_head,
- strbuf_release(&sb);
- sigchain_pop(SIGPIPE);
- return finish_command(&proc);
++ strvec_push(&opt.args, "amend");
++
+ strbuf_addf(&tmp,
+ "%s %s",
+ oid_to_hex(oldoid),
@@ sequencer.c: static int pick_commits(struct repository *r,
- strvec_push(&child.args, "--for-rewrite=rebase");
+ struct child_process notes_cp = CHILD_PROCESS_INIT;
+ struct run_hooks_opt hook_opt;
++
+ run_hooks_opt_init_async(&hook_opt);
+
+ notes_cp.in = open(rebase_path_rewritten_list(), O_RDONLY);
28: 0ab776068d = 27: 964011dfdd transport: convert pre-push hook to use config
29: 601dada804 ! 28: c04822add9 reference-transaction: look for hooks in config
@@ t/t1416-ref-transaction-hooks.sh: test_expect_success 'interleaving hook calls s
EOF
git push ./target-repo.git PRE POST &&
+
+ ## transport.c ##
+@@ transport.c: static int run_pre_push_hook(struct transport *transport,
+ struct strbuf tmp = STRBUF_INIT;
+ struct ref *r;
+ struct string_list to_stdin = STRING_LIST_INIT_DUP;
++
+ run_hooks_opt_init_async(&opt);
+
+ strvec_push(&opt.args, transport->remote->name);
30: d60f2b146e ! 29: ddc6f56bec receive-pack: convert 'update' hook to hook.h
@@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
return status;
}
--static int run_update_hook(struct command *cmd)
+static void hook_output_to_sideband(struct strbuf *output, void *cb_data)
- {
-- const char *argv[5];
-- struct child_process proc = CHILD_PROCESS_INIT;
-- int code;
++{
+ int keepalive_active = 0;
-
-- argv[0] = find_hook("update");
-- if (!argv[0])
-- return 0;
++
+ if (keepalive_in_sec <= 0)
+ use_keepalive = KEEPALIVE_NEVER;
+ if (use_keepalive == KEEPALIVE_ALWAYS)
+ keepalive_active = 1;
-
-- argv[1] = cmd->ref_name;
-- argv[2] = oid_to_hex(&cmd->old_oid);
-- argv[3] = oid_to_hex(&cmd->new_oid);
-- argv[4] = NULL;
++
+ /* send a keepalive if there is no data to write */
+ if (keepalive_active && !output->len) {
+ static const char buf[] = "0005\1";
+ write_or_die(1, buf, sizeof(buf) - 1);
+ return;
+ }
-
-- proc.no_stdin = 1;
-- proc.stdout_to_stderr = 1;
-- proc.err = use_sideband ? -1 : 0;
-- proc.argv = argv;
-- proc.trace2_hook_name = "update";
++
+ if (use_keepalive == KEEPALIVE_AFTER_NUL && !keepalive_active) {
+ const char *first_null = memchr(output->buf, '\0', output->len);
+ if (first_null) {
@@ builtin/receive-pack.c: static int run_receive_hook(struct command *commands,
+ send_sideband(1, 2, output->buf, output->len, use_sideband);
+}
+
-+static int run_update_hook(struct command *cmd)
-+{
+ static int run_update_hook(struct command *cmd)
+ {
+- const char *argv[5];
+- struct child_process proc = CHILD_PROCESS_INIT;
+ struct run_hooks_opt opt;
-+ int code;
+ int code;
+
+- argv[0] = find_hook("update");
+- if (!argv[0])
+- return 0;
+ run_hooks_opt_init_async(&opt);
-+
+
+- argv[1] = cmd->ref_name;
+- argv[2] = oid_to_hex(&cmd->old_oid);
+- argv[3] = oid_to_hex(&cmd->new_oid);
+- argv[4] = NULL;
+ strvec_pushl(&opt.args,
+ cmd->ref_name,
+ oid_to_hex(&cmd->old_oid),
+ oid_to_hex(&cmd->new_oid),
+ NULL);
+- proc.no_stdin = 1;
+- proc.stdout_to_stderr = 1;
+- proc.err = use_sideband ? -1 : 0;
+- proc.argv = argv;
+- proc.trace2_hook_name = "update";
+-
- code = start_command(&proc);
- if (code)
- return code;
31: 1e6898670b ! 30: e1e810869f proc-receive: acquire hook list from hook.h
@@ builtin/receive-pack.c: static int run_proc_receive_hook(struct command *command
- argv[0] = find_hook("proc-receive");
- if (!argv[0]) {
-+ struct strbuf hookname = STRBUF_INIT;
+ struct hook *proc_receive = NULL;
+ struct list_head *pos, *hooks;
+
-+ strbuf_addstr(&hookname, "proc-receive");
-+ hooks = hook_list(&hookname);
++ hooks = hook_list("proc-receive");
+
+ list_for_each(pos, hooks) {
+ if (proc_receive) {
32: 012e3a7a79 ! 31: b8be5a2288 post-update: use hook.h library
@@ builtin/receive-pack.c: static const char *update(struct command *cmd, struct sh
struct command *cmd;
- struct child_process proc = CHILD_PROCESS_INIT;
- const char *hook;
--
++ struct run_hooks_opt opt;
+
- hook = find_hook("post-update");
- if (!hook)
- return;
-+ struct run_hooks_opt opt;
+ run_hooks_opt_init_async(&opt);
for (cmd = commands; cmd; cmd = cmd->next) {
33: 2740bcda6d = 32: 1cc1384eae receive-pack: convert receive hooks to hook.h
34: f201f3af5f = 33: 1bb9a3810c bugreport: use hook_exists instead of find_hook
35: 0956a94cc7 ! 34: 3db7bf3b0d git-send-email: use 'git hook run' for 'sendemail-validate'
@@ git-send-email.perl: sub unique_email_list {
my ($fn, $xfer_encoding) = @_;
- if ($repo) {
-- my $validate_hook = catfile(catdir($repo->repo_path(), 'hooks'),
+- my $validate_hook = catfile($repo->hooks_path(),
- 'sendemail-validate');
- my $hook_error;
- if (-x $validate_hook) {
@@ git-send-email.perl: sub unique_email_list {
- chdir($repo->wc_path() or $repo->repo_path())
- or die("chdir: $!");
- local $ENV{"GIT_DIR"} = $repo->repo_path();
-- $hook_error = "rejected by sendemail-validate hook"
-- if system($validate_hook, $target);
+- $hook_error = system_or_msg([$validate_hook, $target]);
- chdir($cwd_save) or die("chdir: $!");
- }
-- return $hook_error if $hook_error;
+- if ($hook_error) {
+- die sprintf(__("fatal: %s: rejected by sendemail-validate hook\n" .
+- "%s\n" .
+- "warning: no patches were sent\n"), $fn, $hook_error);
+- }
- }
+ my $target = abs_path($fn);
-+ return "rejected by sendemail-validate hook"
-+ if system(("git", "hook", "run", "sendemail-validate", "-a",
-+ $target));
++
++ system_or_die(["git", "hook", "run", "sendemail-validate", "-j1", "-a", $target],
++ sprintf(__("fatal: %s: rejected by sendemail-validate hook\n" .
++ "warning: no patches were sent\n"),
++ $fn));
# Any long lines will be automatically fixed if we use a suitable transfer
# encoding.
## t/t9001-send-email.sh ##
+@@ t/t9001-send-email.sh: test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
+ test_path_is_file my-hooks.ran &&
+ cat >expect <<-EOF &&
+ fatal: longline.patch: rejected by sendemail-validate hook
+- fatal: command '"'"'$PWD/my-hooks/sendemail-validate'"'"' died with exit code 1
+ warning: no patches were sent
+ EOF
+ test_cmp expect actual
+@@ t/t9001-send-email.sh: test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
+ test_path_is_file my-hooks.ran &&
+ cat >expect <<-EOF &&
+ fatal: longline.patch: rejected by sendemail-validate hook
+- fatal: command '"'"'$PWD/my-hooks/sendemail-validate'"'"' died with exit code 1
+ warning: no patches were sent
+ EOF
+ test_cmp expect actual
@@ t/t9001-send-email.sh: test_expect_success $PREREQ 'invoke hook' '
mkdir -p .git/hooks &&
36: 7f05b25392 ! 35: d2a477d9e3 run-command: stop thinking about hooks
@@ hook.c: static int should_include_hookdir(const char *path, enum hookdir_opt cfg
+}
+
+
- struct list_head* hook_list(const struct strbuf* hookname)
+ struct list_head* hook_list(const char* hookname)
{
struct strbuf hook_key = STRBUF_INIT;
-@@ hook.c: struct list_head* hook_list(const struct strbuf* hookname)
+@@ hook.c: struct list_head* hook_list(const char* hookname)
git_config(hook_config_lookup, &cb_data);
if (have_git_dir()) {
-- const char *legacy_hook_path = find_hook(hookname->buf);
-+ const char *legacy_hook_path = find_legacy_hook(hookname->buf);
+- const char *legacy_hook_path = find_hook(hookname);
++ const char *legacy_hook_path = find_legacy_hook(hookname);
/* Unconditionally add legacy hook, but annotate it. */
if (legacy_hook_path) {
37: e9b1f847f2 < -: ---------- docs: unify githooks and git-hook manpages
-: ---------- > 36: 62a3e3b419 doc: clarify fsmonitor-watchman specification
-: ---------- > 37: 5c864de1aa docs: link githooks and git-hook manpages
--
2.31.1.818.g46aad6cb9e-goog
next prev parent reply other threads:[~2021-05-27 0:09 UTC|newest]
Thread overview: 479+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-11 2:10 [PATCH v8 00/37] config-based hooks Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 01/37] doc: propose hooks managed by the config Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 02/37] hook: scaffolding for git-hook subcommand Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 03/37] hook: add list command Emily Shaffer
2021-03-12 8:20 ` Ævar Arnfjörð Bjarmason
2021-03-24 17:31 ` Emily Shaffer
2021-03-25 12:36 ` Ævar Arnfjörð Bjarmason
2021-03-11 2:10 ` [PATCH v8 04/37] hook: include hookdir hook in list Emily Shaffer
2021-03-12 8:30 ` Ævar Arnfjörð Bjarmason
2021-03-24 17:56 ` Emily Shaffer
2021-03-24 19:11 ` Junio C Hamano
2021-03-24 19:23 ` Eric Sunshine
2021-03-24 20:07 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 05/37] hook: teach hook.runHookDir Emily Shaffer
2021-03-12 8:33 ` Ævar Arnfjörð Bjarmason
2021-03-24 18:46 ` Emily Shaffer
2021-03-24 22:38 ` Ævar Arnfjörð Bjarmason
2021-03-11 2:10 ` [PATCH v8 06/37] hook: implement hookcmd.<name>.skip Emily Shaffer
2021-03-12 8:49 ` Ævar Arnfjörð Bjarmason
2021-03-11 2:10 ` [PATCH v8 07/37] parse-options: parse into strvec Emily Shaffer
2021-03-12 8:50 ` Ævar Arnfjörð Bjarmason
2021-03-24 20:34 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 08/37] hook: add 'run' subcommand Emily Shaffer
2021-03-12 8:54 ` Ævar Arnfjörð Bjarmason
2021-03-24 21:29 ` Emily Shaffer
2021-03-12 10:22 ` Junio C Hamano
2021-03-11 2:10 ` [PATCH v8 09/37] hook: introduce hook_exists() Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 10/37] hook: support passing stdin to hooks Emily Shaffer
2021-03-12 9:00 ` Ævar Arnfjörð Bjarmason
2021-03-12 10:22 ` Junio C Hamano
2021-03-11 2:10 ` [PATCH v8 11/37] run-command: allow stdin for run_processes_parallel Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 12/37] hook: allow parallel hook execution Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 13/37] hook: allow specifying working directory for hooks Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 14/37] run-command: add stdin callback for parallelization Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 15/37] hook: provide stdin by string_list or callback Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 16/37] run-command: allow capturing of collated output Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 17/37] hooks: allow callers to capture output Emily Shaffer
2021-03-12 9:08 ` Ævar Arnfjörð Bjarmason
2021-03-24 21:54 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 18/37] commit: use config-based hooks Emily Shaffer
2021-03-12 10:22 ` Junio C Hamano
2021-03-11 2:10 ` [PATCH v8 19/37] am: convert applypatch hooks to use config Emily Shaffer
2021-03-12 10:23 ` Junio C Hamano
2021-03-29 23:39 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 20/37] merge: use config-based hooks for post-merge hook Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 21/37] gc: use hook library for pre-auto-gc hook Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 22/37] rebase: teach pre-rebase to use hook.h Emily Shaffer
2021-03-12 10:24 ` Junio C Hamano
2021-03-11 2:10 ` [PATCH v8 23/37] read-cache: convert post-index-change hook to use config Emily Shaffer
2021-03-12 10:22 ` Junio C Hamano
2021-03-29 23:56 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 24/37] receive-pack: convert push-to-checkout hook to hook.h Emily Shaffer
2021-03-12 10:24 ` Junio C Hamano
2021-03-29 23:59 ` Emily Shaffer
2021-03-30 0:10 ` Junio C Hamano
2021-03-11 2:10 ` [PATCH v8 25/37] git-p4: use 'git hook' to run hooks Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 26/37] hooks: convert 'post-checkout' hook to hook library Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 27/37] hook: convert 'post-rewrite' hook to config Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 28/37] transport: convert pre-push hook to use config Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 29/37] reference-transaction: look for hooks in config Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 30/37] receive-pack: convert 'update' hook to hook.h Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 31/37] proc-receive: acquire hook list from hook.h Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 32/37] post-update: use hook.h library Emily Shaffer
2021-03-12 9:14 ` Ævar Arnfjörð Bjarmason
2021-03-30 0:01 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 33/37] receive-pack: convert receive hooks to hook.h Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 34/37] bugreport: use hook_exists instead of find_hook Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 35/37] git-send-email: use 'git hook run' for 'sendemail-validate' Emily Shaffer
2021-03-12 9:21 ` Ævar Arnfjörð Bjarmason
2021-03-30 0:03 ` Emily Shaffer
2021-03-31 21:47 ` Emily Shaffer
2021-03-31 22:06 ` Junio C Hamano
2021-04-01 18:08 ` Emily Shaffer
2021-04-01 18:55 ` Junio C Hamano
2021-04-02 11:34 ` [PATCH 0/2] git-send-email: refactor duplicate $? checks into a function Ævar Arnfjörð Bjarmason
2021-04-02 11:34 ` [PATCH 1/2] git-send-email: replace "map" in void context with "for" Ævar Arnfjörð Bjarmason
2021-04-02 21:31 ` Junio C Hamano
2021-04-02 21:37 ` Emily Shaffer
2021-04-02 11:34 ` [PATCH 2/2] git-send-email: refactor duplicate $? checks into a function Ævar Arnfjörð Bjarmason
2021-04-02 21:36 ` Junio C Hamano
2021-04-04 9:19 ` [PATCH v2 0/4] refactor duplicate $? checks into a function + improve errors Ævar Arnfjörð Bjarmason
2021-04-04 9:19 ` [PATCH v2 1/4] git-send-email: replace "map" in void context with "for" Ævar Arnfjörð Bjarmason
2021-04-04 9:19 ` [PATCH v2 2/4] git-send-email: refactor duplicate $? checks into a function Ævar Arnfjörð Bjarmason
2021-04-05 19:11 ` Junio C Hamano
2021-04-05 23:47 ` Junio C Hamano
2021-04-08 22:43 ` Junio C Hamano
2021-04-08 22:46 ` Junio C Hamano
2021-04-08 23:54 ` Ævar Arnfjörð Bjarmason
2021-04-09 0:08 ` Junio C Hamano
2021-05-03 20:30 ` Emily Shaffer
2021-04-04 9:19 ` [PATCH v2 3/4] git-send-email: test full --validate output Ævar Arnfjörð Bjarmason
2021-04-04 9:19 ` [PATCH v2 4/4] git-send-email: improve --validate error output Ævar Arnfjörð Bjarmason
2021-04-05 19:14 ` Junio C Hamano
2021-04-06 14:00 ` [PATCH v3 0/3] refactor duplicate $? checks into a function + improve errors Ævar Arnfjörð Bjarmason
2021-04-06 14:00 ` [PATCH v3 1/3] git-send-email: test full --validate output Ævar Arnfjörð Bjarmason
2021-04-06 14:00 ` [PATCH v3 2/3] git-send-email: refactor duplicate $? checks into a function Ævar Arnfjörð Bjarmason
2021-04-06 14:00 ` [PATCH v3 3/3] git-send-email: improve --validate error output Ævar Arnfjörð Bjarmason
2021-04-06 20:33 ` [PATCH v3 0/3] refactor duplicate $? checks into a function + improve errors Junio C Hamano
2021-03-12 23:29 ` [PATCH v8 35/37] git-send-email: use 'git hook run' for 'sendemail-validate' Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 36/37] run-command: stop thinking about hooks Emily Shaffer
2021-03-12 9:23 ` Ævar Arnfjörð Bjarmason
2021-03-30 0:07 ` Emily Shaffer
2021-03-11 2:10 ` [PATCH v8 37/37] docs: unify githooks and git-hook manpages Emily Shaffer
2021-03-12 9:29 ` Ævar Arnfjörð Bjarmason
2021-03-30 0:10 ` Emily Shaffer
2021-04-07 2:36 ` Junio C Hamano
2021-04-08 20:20 ` Jeff Hostetler
2021-04-08 21:17 ` Junio C Hamano
2021-04-08 23:46 ` Emily Shaffer
2021-04-09 0:03 ` Junio C Hamano
2021-03-11 22:26 ` [PATCH v8 00/37] config-based hooks Junio C Hamano
2021-03-12 23:27 ` Emily Shaffer
2021-03-12 9:49 ` Ævar Arnfjörð Bjarmason
2021-03-17 18:41 ` Emily Shaffer
2021-03-17 19:16 ` Emily Shaffer
2021-03-12 11:13 ` Ævar Arnfjörð Bjarmason
2021-03-25 12:41 ` Ævar Arnfjörð Bjarmason
2021-05-27 0:08 ` Emily Shaffer [this message]
2021-05-27 0:08 ` [PATCH v9 01/37] doc: propose hooks managed by the config Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 02/37] hook: introduce git-hook subcommand Emily Shaffer
2021-05-27 2:18 ` Junio C Hamano
2021-05-27 0:08 ` [PATCH v9 03/37] hook: include hookdir hook in list Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 04/37] hook: teach hook.runHookDir Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 05/37] hook: implement hookcmd.<name>.skip Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 06/37] parse-options: parse into strvec Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 07/37] hook: add 'run' subcommand Emily Shaffer
2021-06-03 9:07 ` Ævar Arnfjörð Bjarmason
2021-06-03 22:29 ` Junio C Hamano
2021-05-27 0:08 ` [PATCH v9 08/37] hook: introduce hook_exists() Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 09/37] hook: support passing stdin to hooks Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 10/37] run-command: allow stdin for run_processes_parallel Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 11/37] hook: allow parallel hook execution Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 12/37] hook: allow specifying working directory for hooks Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 13/37] run-command: add stdin callback for parallelization Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 14/37] hook: provide stdin by string_list or callback Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 15/37] run-command: allow capturing of collated output Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 16/37] hooks: allow callers to capture output Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 17/37] commit: use config-based hooks Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 18/37] am: convert applypatch hooks to use config Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 19/37] merge: use config-based hooks for post-merge hook Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 20/37] gc: use hook library for pre-auto-gc hook Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 21/37] rebase: teach pre-rebase to use hook.h Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 22/37] read-cache: convert post-index-change hook to use config Emily Shaffer
2021-05-27 23:04 ` Ævar Arnfjörð Bjarmason
2021-05-28 1:09 ` Taylor Blau
2021-05-31 19:21 ` Felipe Contreras
2021-05-27 0:08 ` [PATCH v9 23/37] receive-pack: convert push-to-checkout hook to hook.h Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 24/37] git-p4: use 'git hook' to run hooks Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 25/37] hooks: convert 'post-checkout' hook to hook library Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 26/37] hook: convert 'post-rewrite' hook to config Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 27/37] transport: convert pre-push hook to use config Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 28/37] reference-transaction: look for hooks in config Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 29/37] receive-pack: convert 'update' hook to hook.h Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 30/37] proc-receive: acquire hook list from hook.h Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 31/37] post-update: use hook.h library Emily Shaffer
2021-06-14 9:09 ` Ævar Arnfjörð Bjarmason
2021-05-27 0:08 ` [PATCH v9 32/37] receive-pack: convert receive hooks to hook.h Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 33/37] bugreport: use hook_exists instead of find_hook Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 34/37] git-send-email: use 'git hook run' for 'sendemail-validate' Emily Shaffer
2021-05-27 11:56 ` Ævar Arnfjörð Bjarmason
2021-05-27 0:08 ` [PATCH v9 35/37] run-command: stop thinking about hooks Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 36/37] doc: clarify fsmonitor-watchman specification Emily Shaffer
2021-05-27 0:08 ` [PATCH v9 37/37] docs: link githooks and git-hook manpages Emily Shaffer
2021-06-03 9:18 ` Ævar Arnfjörð Bjarmason
2021-05-27 11:49 ` [PATCH v9 00/37] propose config-based hooks Ævar Arnfjörð Bjarmason
2021-05-27 13:36 ` Ævar Arnfjörð Bjarmason
2021-05-27 17:46 ` Felipe Contreras
2021-05-28 12:11 ` [PATCH 00/31] minimal restart of "config-based-hooks" Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 01/31] hooks tests: don't leave "actual" nonexisting on failure Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 02/31] gc tests: add a test for the "pre-auto-gc" hook Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 03/31] hook: add 'run' subcommand Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 04/31] run-command.h: move find_hook() to hook.h Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 05/31] hook.c: add a hook_exists() wrapper and use it in bugreport.c Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 06/31] gc: use hook library for pre-auto-gc hook Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 07/31] rebase: teach pre-rebase to use hook.h Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 08/31] am: convert applypatch hooks to use config Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 09/31] hooks: convert 'post-checkout' hook to hook library Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 10/31] merge: use config-based hooks for post-merge hook Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 11/31] git hook run: add an --ignore-missing flag Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 12/31] send-email: use 'git hook run' for 'sendemail-validate' Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 13/31] git-p4: use 'git hook' to run hooks Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 14/31] commit: use hook.h to execute hooks Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 15/31] read-cache: convert post-index-change hook to use config Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 16/31] receive-pack: convert push-to-checkout hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-02 0:51 ` Felipe Contreras
2021-05-28 12:11 ` [PATCH 17/31] run-command: allow stdin for run_processes_parallel Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 18/31] hook: support passing stdin to hooks Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 19/31] am: convert 'post-rewrite' hook to hook.h Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 20/31] run-command: add stdin callback for parallelization Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 21/31] hook: provide stdin by string_list or callback Ævar Arnfjörð Bjarmason
2021-06-02 1:00 ` Felipe Contreras
2021-05-28 12:11 ` [PATCH 22/31] hook: convert 'post-rewrite' hook in sequencer.c to hook.h Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 23/31] transport: convert pre-push hook to use config Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 24/31] reference-transaction: use hook.h to run hooks Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 25/31] run-command: allow capturing of collated output Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 26/31] hooks: allow callers to capture output Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 27/31] receive-pack: convert 'update' hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-02 1:04 ` Felipe Contreras
2021-05-28 12:11 ` [PATCH 28/31] post-update: use hook.h library Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 29/31] receive-pack: convert receive hooks to hook.h Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 30/31] hooks: fix a TOCTOU in "did we run a hook?" heuristic Ævar Arnfjörð Bjarmason
2021-05-28 12:48 ` Bagas Sanjaya
2021-05-28 14:11 ` Ævar Arnfjörð Bjarmason
2021-05-28 12:11 ` [PATCH 31/31] hook-list.h: add a generated list of hooks, like config-list.h Ævar Arnfjörð Bjarmason
2021-06-01 1:00 ` Ævar Arnfjörð Bjarmason
2021-06-01 18:14 ` [PATCH 00/31] minimal restart of "config-based-hooks" Emily Shaffer
2021-06-01 20:50 ` Derrick Stolee
2021-06-02 5:42 ` Felipe Contreras
2021-06-02 7:46 ` Ævar Arnfjörð Bjarmason
2021-06-02 9:34 ` Ævar Arnfjörð Bjarmason
2021-06-02 5:30 ` Felipe Contreras
2021-06-02 7:56 ` Ævar Arnfjörð Bjarmason
2021-06-02 9:39 ` Ævar Arnfjörð Bjarmason
2021-06-25 18:14 ` Felipe Contreras
2021-06-14 10:32 ` [PATCH v2 00/30] Minimal " Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 01/30] hook: add 'run' subcommand Ævar Arnfjörð Bjarmason
2021-06-14 21:33 ` Emily Shaffer
2021-06-15 9:36 ` Ævar Arnfjörð Bjarmason
2021-06-18 22:13 ` Emily Shaffer
2021-06-20 19:30 ` Ævar Arnfjörð Bjarmason
2021-06-21 3:44 ` Junio C Hamano
2021-06-22 0:00 ` Emily Shaffer
2021-06-29 1:12 ` Junio C Hamano
2021-06-25 19:02 ` Felipe Contreras
2021-06-25 19:08 ` Felipe Contreras
2021-06-14 10:32 ` [PATCH v2 02/30] run-command.h: move find_hook() to hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 03/30] hook.c: add a hook_exists() wrapper and use it in bugreport.c Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 04/30] gc: use hook library for pre-auto-gc hook Ævar Arnfjörð Bjarmason
2021-06-14 23:57 ` Emily Shaffer
2021-06-14 10:32 ` [PATCH v2 05/30] rebase: teach pre-rebase to use hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 06/30] am: convert applypatch hooks to use config Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 07/30] hooks: convert 'post-checkout' hook to hook library Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 08/30] merge: use config-based hooks for post-merge hook Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 09/30] git hook run: add an --ignore-missing flag Ævar Arnfjörð Bjarmason
2021-06-14 10:32 ` [PATCH v2 10/30] send-email: use 'git hook run' for 'sendemail-validate' Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 11/30] git-p4: use 'git hook' to run hooks Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 12/30] commit: use hook.h to execute hooks Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 13/30] read-cache: convert post-index-change hook to use config Ævar Arnfjörð Bjarmason
2021-06-25 18:32 ` Felipe Contreras
2021-06-14 10:33 ` [PATCH v2 14/30] receive-pack: convert push-to-checkout hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 15/30] run-command: remove old run_hook_{le,ve}() hook API Ævar Arnfjörð Bjarmason
2021-06-25 18:34 ` Felipe Contreras
2021-06-14 10:33 ` [PATCH v2 16/30] run-command: allow stdin for run_processes_parallel Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 17/30] hook: support passing stdin to hooks Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 18/30] am: convert 'post-rewrite' hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 19/30] run-command: add stdin callback for parallelization Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 20/30] hook: provide stdin by string_list or callback Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 21/30] hook: convert 'post-rewrite' hook in sequencer.c to hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 22/30] transport: convert pre-push hook to use config Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 23/30] reference-transaction: use hook.h to run hooks Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 24/30] run-command: allow capturing of collated output Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 25/30] hooks: allow callers to capture output Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 26/30] receive-pack: convert 'update' hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 27/30] post-update: use hook.h library Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 28/30] receive-pack: convert receive hooks to hook.h Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 29/30] hooks: fix a TOCTOU in "did we run a hook?" heuristic Ævar Arnfjörð Bjarmason
2021-06-14 10:33 ` [PATCH v2 30/30] hook-list.h: add a generated list of hooks, like config-list.h Ævar Arnfjörð Bjarmason
2021-06-15 10:02 ` Ævar Arnfjörð Bjarmason
2021-06-14 20:22 ` [PATCH v2 00/30] Minimal restart of "config-based-hooks" Emily Shaffer
2021-06-16 0:45 ` Junio C Hamano
2021-06-17 10:22 ` [PATCH 00/27] Base for "config-based-hooks" Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 01/27] hook: add 'run' subcommand Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 02/27] gc: use hook library for pre-auto-gc hook Ævar Arnfjörð Bjarmason
2021-07-22 21:58 ` Emily Shaffer
2021-06-17 10:22 ` [PATCH 03/27] rebase: teach pre-rebase to use hook.h Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 04/27] am: convert applypatch hooks to use config Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 05/27] hooks: convert 'post-checkout' hook to hook library Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 06/27] merge: use config-based hooks for post-merge hook Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 07/27] git hook run: add an --ignore-missing flag Ævar Arnfjörð Bjarmason
2021-07-02 23:47 ` Emily Shaffer
2021-06-17 10:22 ` [PATCH 08/27] send-email: use 'git hook run' for 'sendemail-validate' Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 09/27] git-p4: use 'git hook' to run hooks Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 10/27] commit: use hook.h to execute hooks Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 11/27] read-cache: convert post-index-change hook to use config Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 12/27] receive-pack: convert push-to-checkout hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 13/27] run-command: remove old run_hook_{le,ve}() hook API Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 14/27] run-command: allow stdin for run_processes_parallel Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 15/27] hook: support passing stdin to hooks Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 16/27] am: convert 'post-rewrite' hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 17/27] run-command: add stdin callback for parallelization Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 18/27] hook: provide stdin by string_list or callback Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 19/27] hook: convert 'post-rewrite' hook in sequencer.c to hook.h Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 20/27] transport: convert pre-push hook to use config Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 21/27] reference-transaction: use hook.h to run hooks Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 22/27] run-command: allow capturing of collated output Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 23/27] hooks: allow callers to capture output Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 24/27] receive-pack: convert 'update' hook to hook.h Ævar Arnfjörð Bjarmason
2021-06-17 10:22 ` [PATCH 25/27] post-update: use hook.h library Ævar Arnfjörð Bjarmason
2021-06-17 10:23 ` [PATCH 26/27] receive-pack: convert receive hooks to hook.h Ævar Arnfjörð Bjarmason
2021-06-17 10:23 ` [PATCH 27/27] hooks: fix a TOCTOU in "did we run a hook?" heuristic Ævar Arnfjörð Bjarmason
2021-06-18 22:09 ` Emily Shaffer
2021-07-15 23:25 ` [PATCH 0/9] config-based hooks restarted Emily Shaffer
2021-07-15 23:25 ` [PATCH 1/9] hook: run a list of hooks instead Emily Shaffer
2021-07-15 23:25 ` [PATCH 2/9] hook: allow parallel hook execution Emily Shaffer
2021-07-16 8:36 ` Ævar Arnfjörð Bjarmason
2021-07-22 21:12 ` Emily Shaffer
2021-07-23 9:30 ` Ævar Arnfjörð Bjarmason
2021-07-15 23:25 ` [PATCH 3/9] hook: introduce "git hook list" Emily Shaffer
2021-07-16 8:52 ` Ævar Arnfjörð Bjarmason
2021-07-22 22:18 ` Emily Shaffer
2021-07-23 9:29 ` Ævar Arnfjörð Bjarmason
2021-07-15 23:25 ` [PATCH 4/9] hook: treat hookdir hook specially Emily Shaffer
2021-07-16 8:58 ` Ævar Arnfjörð Bjarmason
2021-07-22 22:24 ` Emily Shaffer
2021-07-23 9:26 ` Ævar Arnfjörð Bjarmason
2021-07-23 17:33 ` Felipe Contreras
2021-07-23 18:22 ` Eric Sunshine
2021-07-23 20:02 ` Felipe Contreras
2021-07-15 23:25 ` [PATCH 5/9] hook: allow running non-native hooks Emily Shaffer
2021-07-15 23:26 ` [PATCH 6/9] hook: include hooks from the config Emily Shaffer
2021-07-16 9:01 ` Ævar Arnfjörð Bjarmason
2021-07-22 22:51 ` Emily Shaffer
2021-07-23 9:22 ` Ævar Arnfjörð Bjarmason
2021-07-15 23:26 ` [PATCH 7/9] hook: allow out-of-repo 'git hook' invocations Emily Shaffer
2021-07-16 8:33 ` Ævar Arnfjörð Bjarmason
2021-07-22 23:07 ` Emily Shaffer
2021-07-23 9:18 ` Ævar Arnfjörð Bjarmason
2021-07-15 23:26 ` [PATCH 8/9] hook: teach 'hookcmd' config to alias hook scripts Emily Shaffer
2021-07-16 9:13 ` Ævar Arnfjörð Bjarmason
2021-07-22 23:31 ` Emily Shaffer
2021-07-23 7:41 ` Ævar Arnfjörð Bjarmason
2021-08-04 20:38 ` Emily Shaffer
2021-08-05 0:17 ` Ævar Arnfjörð Bjarmason
2021-08-05 21:45 ` Emily Shaffer
2021-08-05 22:26 ` Ævar Arnfjörð Bjarmason
2021-08-06 20:18 ` Emily Shaffer
2021-08-04 21:49 ` Jonathan Tan
2021-07-15 23:26 ` [PATCH 9/9] hook: implement hookcmd.<name>.skip Emily Shaffer
2021-07-28 20:39 ` [PATCH 00/27] Base for "config-based-hooks" Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 00/36] Run hooks via "git run hook" & hook library Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 01/36] Makefile: mark "check" target as .PHONY Ævar Arnfjörð Bjarmason
2021-08-20 0:04 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 02/36] Makefile: stop hardcoding {command,config}-list.h Ævar Arnfjörð Bjarmason
2021-08-20 0:03 ` Emily Shaffer
2021-08-24 14:22 ` Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 03/36] Makefile: remove an out-of-date comment Ævar Arnfjörð Bjarmason
2021-08-20 0:05 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 04/36] hook.[ch]: move find_hook() to this new library Ævar Arnfjörð Bjarmason
2021-08-20 0:08 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 05/36] hook.c: add a hook_exists() wrapper and use it in bugreport.c Ævar Arnfjörð Bjarmason
2021-08-20 0:09 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 06/36] hook.c users: use "hook_exists()" insted of "find_hook()" Ævar Arnfjörð Bjarmason
2021-08-20 0:10 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 07/36] hook-list.h: add a generated list of hooks, like config-list.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 08/36] hook: add 'run' subcommand Ævar Arnfjörð Bjarmason
2021-08-04 10:15 ` Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 09/36] gc: use hook library for pre-auto-gc hook Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 10/36] rebase: convert pre-rebase to use hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 11/36] am: convert applypatch " Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 12/36] hooks: convert 'post-checkout' hook to hook library Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 13/36] merge: convert post-merge to use hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 14/36] git hook run: add an --ignore-missing flag Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 15/36] send-email: use 'git hook run' for 'sendemail-validate' Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 16/36] git-p4: use 'git hook' to run hooks Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 17/36] commit: convert {pre-commit,prepare-commit-msg} hook to hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 18/36] read-cache: convert post-index-change to use hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 19/36] receive-pack: convert push-to-checkout hook to hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 20/36] run-command: remove old run_hook_{le,ve}() hook API Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 21/36] run-command: allow stdin for run_processes_parallel Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 22/36] hook: support passing stdin to hooks Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 23/36] am: convert 'post-rewrite' hook to hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 24/36] run-command: add stdin callback for parallelization Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 25/36] hook: provide stdin by string_list or callback Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 26/36] hook: convert 'post-rewrite' hook in sequencer.c to hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 27/36] transport: convert pre-push hook " Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 28/36] hook tests: test for exact "pre-push" hook input Ævar Arnfjörð Bjarmason
2021-08-20 0:16 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 29/36] hook tests: use a modern style for "pre-push" tests Ævar Arnfjörð Bjarmason
2021-08-20 0:18 ` Emily Shaffer
2021-08-03 19:38 ` [PATCH v4 30/36] reference-transaction: use hook.h to run hooks Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 31/36] run-command: allow capturing of collated output Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 32/36] hooks: allow callers to capture output Ævar Arnfjörð Bjarmason
2021-08-03 19:38 ` [PATCH v4 33/36] receive-pack: convert 'update' hook to hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:39 ` [PATCH v4 34/36] post-update: use hook.h library Ævar Arnfjörð Bjarmason
2021-08-03 19:39 ` [PATCH v4 35/36] receive-pack: convert receive hooks to hook.h Ævar Arnfjörð Bjarmason
2021-08-03 19:39 ` [PATCH v4 36/36] hooks: fix a TOCTOU in "did we run a hook?" heuristic Ævar Arnfjörð Bjarmason
2021-08-12 0:42 ` [PATCH v2 0/6] config-based hooks restarted Emily Shaffer
2021-08-12 0:42 ` [PATCH v2 1/6] hook: run a list of hooks instead Emily Shaffer
2021-08-12 17:25 ` Junio C Hamano
2021-08-16 23:38 ` Emily Shaffer
2021-08-12 0:42 ` [PATCH v2 2/6] hook: allow parallel hook execution Emily Shaffer
2021-08-12 17:51 ` Junio C Hamano
2021-08-16 23:59 ` Emily Shaffer
2021-08-12 0:42 ` [PATCH v2 3/6] hook: introduce "git hook list" Emily Shaffer
2021-08-12 18:59 ` Junio C Hamano
2021-08-17 0:36 ` Emily Shaffer
2021-08-12 0:42 ` [PATCH v2 4/6] hook: allow running non-native hooks Emily Shaffer
2021-08-12 19:08 ` Junio C Hamano
2021-08-18 20:51 ` Emily Shaffer
2021-08-18 21:14 ` Emily Shaffer
2021-08-18 21:24 ` Junio C Hamano
2021-08-12 0:42 ` [PATCH v2 5/6] hook: include hooks from the config Emily Shaffer
2021-08-12 20:48 ` Junio C Hamano
2021-08-19 0:09 ` Emily Shaffer
2021-08-12 0:42 ` [PATCH v2 6/6] hook: allow out-of-repo 'git hook' invocations Emily Shaffer
2021-08-12 4:47 ` [PATCH v2 0/6] config-based hooks restarted Junio C Hamano
2021-08-12 5:02 ` Junio C Hamano
2021-08-16 22:31 ` Emily Shaffer
2021-08-19 3:34 ` [PATCH v3 " Emily Shaffer
2021-08-19 3:34 ` [PATCH v3 1/6] hook: run a list of hooks instead Emily Shaffer
2021-08-24 14:56 ` Ævar Arnfjörð Bjarmason
2021-08-26 21:16 ` Emily Shaffer
2021-08-27 11:15 ` Ævar Arnfjörð Bjarmason
2021-08-19 3:34 ` [PATCH v3 2/6] hook: allow parallel hook execution Emily Shaffer
2021-08-24 15:01 ` Ævar Arnfjörð Bjarmason
2021-08-24 16:13 ` Eric Sunshine
2021-08-26 22:36 ` Emily Shaffer
2021-08-19 3:34 ` [PATCH v3 3/6] hook: introduce "git hook list" Emily Shaffer
2021-08-24 15:08 ` Ævar Arnfjörð Bjarmason
2021-08-26 21:43 ` Emily Shaffer
2021-08-24 15:53 ` Ævar Arnfjörð Bjarmason
2021-08-26 22:38 ` Emily Shaffer
2021-08-19 3:34 ` [PATCH v3 4/6] hook: allow running non-native hooks Emily Shaffer
2021-08-24 15:55 ` Ævar Arnfjörð Bjarmason
2021-08-26 22:50 ` Emily Shaffer
2021-08-27 0:22 ` Junio C Hamano
2021-08-19 3:34 ` [PATCH v3 5/6] hook: include hooks from the config Emily Shaffer
2021-08-19 22:39 ` Junio C Hamano
2021-08-19 23:43 ` Emily Shaffer
2021-08-19 23:48 ` Junio C Hamano
2021-08-24 19:30 ` Ævar Arnfjörð Bjarmason
2021-08-31 19:05 ` Emily Shaffer
2021-08-19 3:34 ` [PATCH v3 6/6] hook: allow out-of-repo 'git hook' invocations Emily Shaffer
2021-08-24 20:12 ` Ævar Arnfjörð Bjarmason
2021-08-24 20:38 ` Randall S. Becker
2021-08-24 22:45 ` Ævar Arnfjörð Bjarmason
2021-08-31 21:09 ` Emily Shaffer
2021-08-24 20:29 ` [PATCH v3 0/6] config-based hooks restarted Ævar Arnfjörð Bjarmason
2021-09-02 22:01 ` Emily Shaffer
2021-09-09 12:41 ` [PATCH v4 0/5] " Ævar Arnfjörð Bjarmason
2021-09-09 12:41 ` [PATCH v4 1/5] hook: run a list of hooks instead Ævar Arnfjörð Bjarmason
2021-09-09 12:59 ` [PATCH v4] fixup! " Ævar Arnfjörð Bjarmason
2021-09-09 12:42 ` [PATCH v4 2/5] hook: allow parallel hook execution Ævar Arnfjörð Bjarmason
2021-09-09 12:42 ` [PATCH v4 3/5] hook: introduce "git hook list" Ævar Arnfjörð Bjarmason
2021-09-09 12:42 ` [PATCH v4 4/5] hook: include hooks from the config Ævar Arnfjörð Bjarmason
2021-09-09 12:42 ` [PATCH v4 5/5] hook: allow out-of-repo 'git hook' invocations Ævar Arnfjörð Bjarmason
2021-08-19 0:17 ` [PATCH v4 00/36] Run hooks via "git run hook" & hook library Emily Shaffer
2021-08-19 23:40 ` Emily Shaffer
2021-09-02 7:21 ` Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 " Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 01/36] Makefile: mark "check" target as .PHONY Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 02/36] Makefile: stop hardcoding {command,config}-list.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 03/36] Makefile: remove an out-of-date comment Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 04/36] hook.[ch]: move find_hook() from run-command.c to hook.c Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 05/36] hook.c: add a hook_exists() wrapper and use it in bugreport.c Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 06/36] hook.c users: use "hook_exists()" instead of "find_hook()" Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 07/36] hook-list.h: add a generated list of hooks, like config-list.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 08/36] hook: add 'run' subcommand Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 09/36] gc: use hook library for pre-auto-gc hook Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 10/36] rebase: convert pre-rebase to use hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 11/36] am: convert applypatch " Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 12/36] hooks: convert 'post-checkout' hook to hook library Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 13/36] merge: convert post-merge to use hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 14/36] git hook run: add an --ignore-missing flag Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 15/36] send-email: use 'git hook run' for 'sendemail-validate' Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 16/36] git-p4: use 'git hook' to run hooks Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 17/36] commit: convert {pre-commit,prepare-commit-msg} hook to hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 18/36] read-cache: convert post-index-change to use hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 19/36] receive-pack: convert push-to-checkout hook to hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 20/36] run-command: remove old run_hook_{le,ve}() hook API Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 21/36] run-command: allow stdin for run_processes_parallel Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 22/36] hook: support passing stdin to hooks Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 23/36] am: convert 'post-rewrite' hook to hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 24/36] run-command: add stdin callback for parallelization Ævar Arnfjörð Bjarmason
2021-10-06 11:03 ` ab/config-based-hooks-N status (was Re: [PATCH v5 24/36] run-command: add stdin callback for parallelization) Ævar Arnfjörð Bjarmason
2021-10-12 12:59 ` Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 25/36] hook: provide stdin by string_list or callback Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 26/36] hook: convert 'post-rewrite' hook in sequencer.c to hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 27/36] transport: convert pre-push hook " Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 28/36] hook tests: test for exact "pre-push" hook input Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 29/36] hook tests: use a modern style for "pre-push" tests Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 30/36] reference-transaction: use hook.h to run hooks Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 31/36] run-command: allow capturing of collated output Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 32/36] hooks: allow callers to capture output Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 33/36] receive-pack: convert 'update' hook to hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 34/36] post-update: use hook.h library Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 35/36] receive-pack: convert receive hooks to hook.h Ævar Arnfjörð Bjarmason
2021-09-02 13:11 ` [PATCH v5 36/36] hooks: fix a TOCTOU in "did we run a hook?" heuristic Ævar Arnfjörð Bjarmason
2021-06-25 18:22 ` [PATCH v2 00/30] Minimal restart of "config-based-hooks" Felipe Contreras
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210527000856.695702-1-emilyshaffer@google.com \
--to=emilyshaffer@google.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=james@jramsay.com.au \
--cc=jonathantanmy@google.com \
--cc=jrnieder@gmail.com \
--cc=peff@peff.net \
--cc=phillip.wood123@gmail.com \
--cc=sandals@crustytoothpaste.net \
--cc=steadmon@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).