Merge branch 'ab/config-based-hooks-1'

Mostly preliminary clean-up in the hook API.

* ab/config-based-hooks-1:
  hook-list.h: add a generated list of hooks, like config-list.h
  hook.c users: use "hook_exists()" instead of "find_hook()"
  hook.c: add a hook_exists() wrapper and use it in bugreport.c
  hook.[ch]: move find_hook() from run-command.c to hook.c
  Makefile: remove an out-of-date comment
  Makefile: don't perform "mv $@+ $@" dance for $(GENERATED_H)
  Makefile: stop hardcoding {command,config}-list.h
  Makefile: mark "check" target as .PHONY
This commit is contained in:
Junio C Hamano 2021-10-13 15:15:57 -07:00
commit a5e61a4225
19 changed files with 127 additions and 100 deletions

1
.gitignore vendored
View file

@ -190,6 +190,7 @@
/gitweb/static/gitweb.min.*
/config-list.h
/command-list.h
/hook-list.h
*.tar.gz
*.dsc
*.deb

View file

@ -817,6 +817,10 @@ XDIFF_LIB = xdiff/lib.a
GENERATED_H += command-list.h
GENERATED_H += config-list.h
GENERATED_H += hook-list.h
.PHONY: generated-hdrs
generated-hdrs: $(GENERATED_H)
LIB_H := $(sort $(patsubst ./%,%,$(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
$(FIND) . \
@ -902,6 +906,7 @@ LIB_OBJS += hash-lookup.o
LIB_OBJS += hashmap.o
LIB_OBJS += help.o
LIB_OBJS += hex.o
LIB_OBJS += hook.o
LIB_OBJS += ident.o
LIB_OBJS += json-writer.o
LIB_OBJS += kwset.o
@ -2211,8 +2216,9 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
$(filter %.o,$^) $(LIBS)
help.sp help.s help.o: command-list.h
hook.sp hook.s hook.o: hook-list.h
builtin/help.sp builtin/help.s builtin/help.o: config-list.h GIT-PREFIX
builtin/help.sp builtin/help.s builtin/help.o: config-list.h hook-list.h GIT-PREFIX
builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
'-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
'-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \
@ -2235,15 +2241,17 @@ $(BUILT_INS): git$X
config-list.h: generate-configlist.sh
config-list.h: Documentation/*config.txt Documentation/config/*.txt
$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh \
>$@+ && mv $@+ $@
$(QUIET_GEN)$(SHELL_PATH) ./generate-configlist.sh >$@
command-list.h: generate-cmdlist.sh command-list.txt
command-list.h: $(wildcard Documentation/git*.txt)
$(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh \
$(patsubst %,--exclude-program %,$(EXCLUDED_PROGRAMS)) \
command-list.txt >$@+ && mv $@+ $@
command-list.txt >$@
hook-list.h: generate-hooklist.sh Documentation/githooks.txt
$(QUIET_GEN)$(SHELL_PATH) ./generate-hooklist.sh >$@
SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
@ -2505,13 +2513,6 @@ ifneq ($(dep_files_present),)
include $(dep_files_present)
endif
else
# Dependencies on header files, for platforms that do not support
# the gcc -MMD option.
#
# Dependencies on automatically generated headers such as command-list.h
# should _not_ be included here, since they are necessary even when
# building an object for the first time.
$(OBJECTS): $(LIB_H) $(GENERATED_H)
endif
@ -2909,7 +2910,7 @@ $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
.PHONY: sparse $(SP_OBJ)
sparse: $(SP_OBJ)
EXCEPT_HDRS := command-list.h config-list.h unicode-width.h compat/% xdiff/%
EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/%
ifndef GCRYPT_SHA256
EXCEPT_HDRS += sha256/gcrypt.h
endif
@ -2931,7 +2932,8 @@ hdr-check: $(HCO)
style:
git clang-format --style file --diff --extensions c,h
check: config-list.h command-list.h
.PHONY: check
check: $(GENERATED_H)
@if sparse; \
then \
echo >&2 "Use 'make sparse' instead"; \

View file

@ -11,6 +11,7 @@
#include "parse-options.h"
#include "dir.h"
#include "run-command.h"
#include "hook.h"
#include "quote.h"
#include "tempfile.h"
#include "lockfile.h"

View file

@ -3,7 +3,8 @@
#include "strbuf.h"
#include "help.h"
#include "compat/compiler.h"
#include "run-command.h"
#include "hook.h"
#include "hook-list.h"
static void get_system_info(struct strbuf *sys_info)
@ -41,39 +42,7 @@ static void get_system_info(struct strbuf *sys_info)
static void get_populated_hooks(struct strbuf *hook_info, int nongit)
{
/*
* NEEDSWORK: Doesn't look like there is a list of all possible hooks;
* so below is a transcription of `git help hooks`. Later, this should
* be replaced with some programmatically generated list (generated from
* doc or else taken from some library which tells us about all the
* hooks)
*/
static const char *hook[] = {
"applypatch-msg",
"pre-applypatch",
"post-applypatch",
"pre-commit",
"pre-merge-commit",
"prepare-commit-msg",
"commit-msg",
"post-commit",
"pre-rebase",
"post-checkout",
"post-merge",
"pre-push",
"pre-receive",
"update",
"post-receive",
"post-update",
"push-to-checkout",
"pre-auto-gc",
"post-rewrite",
"sendemail-validate",
"fsmonitor-watchman",
"p4-pre-submit",
"post-index-change",
};
int i;
const char **p;
if (nongit) {
strbuf_addstr(hook_info,
@ -81,9 +50,12 @@ static void get_populated_hooks(struct strbuf *hook_info, int nongit)
return;
}
for (i = 0; i < ARRAY_SIZE(hook); i++)
if (find_hook(hook[i]))
strbuf_addf(hook_info, "%s\n", hook[i]);
for (p = hook_name_list; *p; p++) {
const char *hook = *p;
if (hook_exists(hook))
strbuf_addf(hook_info, "%s\n", hook);
}
}
static const char * const bugreport_usage[] = {

View file

@ -19,6 +19,7 @@
#include "revision.h"
#include "wt-status.h"
#include "run-command.h"
#include "hook.h"
#include "refs.h"
#include "log-tree.h"
#include "strbuf.h"
@ -1051,7 +1052,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
return 0;
}
if (!no_verify && find_hook("pre-commit")) {
if (!no_verify && hook_exists("pre-commit")) {
/*
* Re-read the index as pre-commit hook could have updated it,
* and write it out as a tree. We must do this before we invoke

View file

@ -13,6 +13,7 @@
#include "builtin.h"
#include "lockfile.h"
#include "run-command.h"
#include "hook.h"
#include "diff.h"
#include "diff-merges.h"
#include "refs.h"
@ -849,7 +850,7 @@ static void prepare_to_commit(struct commit_list *remoteheads)
* and write it out as a tree. We must do this before we invoke
* the editor and after we invoke run_status above.
*/
if (find_hook("pre-merge-commit"))
if (hook_exists("pre-merge-commit"))
discard_cache();
read_cache_from(index_file);
strbuf_addbuf(&msg, &merge_msg);

View file

@ -7,6 +7,7 @@
#include "pkt-line.h"
#include "sideband.h"
#include "run-command.h"
#include "hook.h"
#include "exec-cmd.h"
#include "commit.h"
#include "object.h"
@ -1463,7 +1464,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w
strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
if (!find_hook(push_to_checkout_hook))
if (!hook_exists(push_to_checkout_hook))
retval = push_to_deploy(sha1, &env, work_tree);
else
retval = push_to_checkout(sha1, &env, work_tree);

View file

@ -8,6 +8,7 @@
#include "branch.h"
#include "refs.h"
#include "run-command.h"
#include "hook.h"
#include "sigchain.h"
#include "submodule.h"
#include "utf8.h"

View file

@ -92,7 +92,7 @@ The Steps of Build Git with VS2008
the git operations.
3. Inside Git's directory run the command:
make command-list.h config-list.h
make generated-hdrs
to generate the header file needed to compile git.
4. Then either build Git with the GNU Make Makefile in the Git projects

View file

@ -739,9 +739,9 @@ vcxproj:
echo '</Project>') >git-remote-http/LinkOrCopyRemoteHttp.targets
git add -f git/LinkOrCopyBuiltins.targets git-remote-http/LinkOrCopyRemoteHttp.targets
# Add command-list.h and config-list.h
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 config-list.h command-list.h
git add -f config-list.h command-list.h
# Add generated headers
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(GENERATED_H)
git add -f $(GENERATED_H)
# Add scripts
rm -f perl/perl.mak

View file

@ -624,6 +624,13 @@ if(NOT EXISTS ${CMAKE_BINARY_DIR}/config-list.h)
OUTPUT_FILE ${CMAKE_BINARY_DIR}/config-list.h)
endif()
if(NOT EXISTS ${CMAKE_BINARY_DIR}/hook-list.h)
message("Generating hook-list.h")
execute_process(COMMAND ${SH_EXE} ${CMAKE_SOURCE_DIR}/generate-hooklist.sh
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_FILE ${CMAKE_BINARY_DIR}/hook-list.h)
endif()
include_directories(${CMAKE_BINARY_DIR})
#build

20
generate-hooklist.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/sh
#
# Usage: ./generate-hooklist.sh >hook-list.h
cat <<EOF
/* Automatically generated by generate-hooklist.sh */
static const char *hook_name_list[] = {
EOF
sed -n \
-e '/^~~~~*$/ {x; s/^.*$/ "&",/; p;}' \
-e 'x' \
<Documentation/githooks.txt |
LC_ALL=C sort
cat <<EOF
NULL,
};
EOF

42
hook.c Normal file
View file

@ -0,0 +1,42 @@
#include "cache.h"
#include "hook.h"
#include "run-command.h"
const char *find_hook(const char *name)
{
static struct strbuf path = STRBUF_INIT;
strbuf_reset(&path);
strbuf_git_path(&path, "hooks/%s", name);
if (access(path.buf, X_OK) < 0) {
int err = errno;
#ifdef STRIP_EXTENSION
strbuf_addstr(&path, STRIP_EXTENSION);
if (access(path.buf, X_OK) >= 0)
return path.buf;
if (errno == EACCES)
err = errno;
#endif
if (err == EACCES && advice_enabled(ADVICE_IGNORED_HOOK)) {
static struct string_list advise_given = STRING_LIST_INIT_DUP;
if (!string_list_lookup(&advise_given, name)) {
string_list_insert(&advise_given, name);
advise(_("The '%s' hook was ignored because "
"it's not set as executable.\n"
"You can disable this warning with "
"`git config advice.ignoredHook false`."),
path.buf);
}
}
return NULL;
}
return path.buf;
}
int hook_exists(const char *name)
{
return !!find_hook(name);
}

16
hook.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef HOOK_H
#define HOOK_H
/*
* Returns the path to the hook file, or NULL if the hook is missing
* or disabled. Note that this points to static storage that will be
* overwritten by further calls to find_hook and run_hook_*.
*/
const char *find_hook(const char *name);
/**
* A boolean version of find_hook()
*/
int hook_exists(const char *hookname);
#endif

1
refs.c
View file

@ -10,6 +10,7 @@
#include "refs.h"
#include "refs/refs-internal.h"
#include "run-command.h"
#include "hook.h"
#include "object-store.h"
#include "object.h"
#include "tag.h"

View file

@ -9,6 +9,7 @@
#include "quote.h"
#include "config.h"
#include "packfile.h"
#include "hook.h"
void child_process_init(struct child_process *child)
{
@ -1322,40 +1323,6 @@ int async_with_fork(void)
#endif
}
const char *find_hook(const char *name)
{
static struct strbuf path = STRBUF_INIT;
strbuf_reset(&path);
strbuf_git_path(&path, "hooks/%s", name);
if (access(path.buf, X_OK) < 0) {
int err = errno;
#ifdef STRIP_EXTENSION
strbuf_addstr(&path, STRIP_EXTENSION);
if (access(path.buf, X_OK) >= 0)
return path.buf;
if (errno == EACCES)
err = errno;
#endif
if (err == EACCES && advice_enabled(ADVICE_IGNORED_HOOK)) {
static struct string_list advise_given = STRING_LIST_INIT_DUP;
if (!string_list_lookup(&advise_given, name)) {
string_list_insert(&advise_given, name);
advise(_("The '%s' hook was ignored because "
"it's not set as executable.\n"
"You can disable this warning with "
"`git config advice.ignoredHook false`."),
path.buf);
}
}
return NULL;
}
return path.buf;
}
int run_hook_ve(const char *const *env, const char *name, va_list args)
{
struct child_process hook = CHILD_PROCESS_INIT;

View file

@ -224,13 +224,6 @@ int finish_command_in_signal(struct child_process *);
*/
int run_command(struct child_process *);
/*
* Returns the path to the hook file, or NULL if the hook is missing
* or disabled. Note that this points to static storage that will be
* overwritten by further calls to find_hook and run_hook_*.
*/
const char *find_hook(const char *name);
/**
* Run a hook.
* The first argument is a pathname to an index file, or NULL

View file

@ -8,6 +8,7 @@
#include "sequencer.h"
#include "tag.h"
#include "run-command.h"
#include "hook.h"
#include "exec-cmd.h"
#include "utf8.h"
#include "cache-tree.h"
@ -1459,7 +1460,7 @@ static int try_to_commit(struct repository *r,
}
}
if (find_hook("prepare-commit-msg")) {
if (hook_exists("prepare-commit-msg")) {
res = run_prepare_commit_msg_hook(r, msg, hook_commit);
if (res)
goto out;

View file

@ -1,7 +1,7 @@
#include "cache.h"
#include "config.h"
#include "transport.h"
#include "run-command.h"
#include "hook.h"
#include "pkt-line.h"
#include "fetch-pack.h"
#include "remote.h"