git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Rafael Santiago via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Rafael Santiago <voidbrainvoid@tutanota.com>,
	rafael-santiago <voidbrainvoid@tutanota.com>
Subject: [PATCH] Give support for hooks based on platform
Date: Sat, 21 Aug 2021 20:00:07 +0000	[thread overview]
Message-ID: <pull.1069.git.git.1629576007891.gitgitgadget@gmail.com> (raw)

From: rafael-santiago <voidbrainvoid@tutanota.com>

The idea behind this commit can be useful for teams
that share git-hooks into a custom directory and
dealing with projects that must be developed,
built, maintained on several different platforms.

This commit allows the execution of git hooks
based on the current operating system.
A "native hook" is defined in the form:
    hooks/hook-name_platform
Where platform must be equivalent to the
content returned in sysname field in utsname
struct when calling uname() [but all normalized
in lowercase].

On Windows, independent of version, flavor, SP,
whatever it is simply "windows".

When a native hook is not found the standard
hook (.git/hook/hook-name), if found is executed,
of course. In other words, the hook without a
platform postfix (_yyz) is the standard hook.
When native hook is not set as executable but
standard is set, the standard will be executed.

The main motivation of this extension is to
reduce dependency of scripting languages,
logical trinkets etc just to execute minor
tasks during scm events that could be done
natively but differently from a platform
to another. Less dependencies, cleaner
repos: a small step for a better world
for any software developer.

Signed-off-by: Rafael Santiago <voidbrainvoid@tutanota.com>
---
    Give support for hooks based on platform
    
    The idea behind this commit can be useful for teams that share git-hooks
    into a custom directory and dealing with projects that must be
    developed, built, maintained on several different platforms.
    
    This commit allows the execution of git hooks based on the current
    operating system. A "native hook" is defined in the form:
    hooks/hook-name_platform
    
    Where platform must be equivalent to the content returned in sysname
    field in utsname struct when calling uname() [but all normalized in
    lowercase].
    
    On Windows, independent of version, flavor, SP, whatever it is simply
    "windows".
    
    When a native hook is not found the standard hook (.git/hook/hook-name),
    if found is executed, of course. In other words, the hook without a
    platform postfix (_yyz) is the standard hook. When native hook is not
    set as executable but standard is set, the standard will be executed.
    
    The main motivation of this extension is to reduce dependency of
    scripting languages, logical trinkets etc just to execute minor tasks
    during scm events that could be done natively but differently from a
    platform to another. Less dependencies, cleaner repos: a small step for
    a better world for any software developer.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1069%2Frafael-santiago%2Fmaster-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1069/rafael-santiago/master-v1
Pull-Request: https://github.com/git/git/pull/1069

 run-command.c                     | 41 ++++++++++++++++++++
 t/t7527-pre-commit-native-hook.sh | 63 +++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)
 create mode 100755 t/t7527-pre-commit-native-hook.sh

diff --git a/run-command.c b/run-command.c
index f72e72cce73..973c1a3434b 100644
--- a/run-command.c
+++ b/run-command.c
@@ -1319,9 +1319,50 @@ int async_with_fork(void)
 #endif
 }
 
+static inline const char *platform_name(void)
+{
+	static const char *platform = NULL;
+#ifndef GIT_WINDOWS_NATIVE
+	static struct utsname un = { 0 };
+#endif
+	if (platform != NULL)
+		return platform;
+
+#ifndef GIT_WINDOWS_NATIVE
+	if (uname(&un) == 0) {
+		for (size_t s = 0; un.sysname[s] != 0; s++)
+			un.sysname[s] = tolower(un.sysname[s]);
+		platform = un.sysname;
+	}
+#else
+    platform = "windows";
+#endif
+
+    return platform;
+}
+
+static const char *find_native_hook(const char *name)
+{
+	char native_name[64] = "";
+	const char *platform = NULL;
+	if (name == NULL || strstr(name, "_") != NULL)
+		return NULL;
+
+	platform = platform_name();
+	if (platform == NULL)
+		return NULL;
+
+	if (snprintf(native_name, sizeof(native_name) - 1, "%s_%s", name, platform) >= sizeof(native_name) - 1)
+		return NULL;
+	return find_hook(native_name);
+}
+
 const char *find_hook(const char *name)
 {
+	const char *native_hook = find_native_hook(name);
 	static struct strbuf path = STRBUF_INIT;
+	if (native_hook != NULL)
+		return native_hook;
 
 	strbuf_reset(&path);
 	strbuf_git_path(&path, "hooks/%s", name);
diff --git a/t/t7527-pre-commit-native-hook.sh b/t/t7527-pre-commit-native-hook.sh
new file mode 100755
index 00000000000..f3835f943af
--- /dev/null
+++ b/t/t7527-pre-commit-native-hook.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+test_description='Test native hooks extension'
+
+. ./test-lib.sh
+
+expected_platform=$(uname -s | tr A-Z a-z)
+
+if [ $(expr substr $(uname -s | tr A-Z a-z) 1 5) == "mingw" ] ; then
+    expected_platform="windows"
+fi
+
+test_expect_success 'set standard and native pre-commit hooks' '
+	mkdir -p test-repo &&
+	cd test-repo &&
+	git init &&
+	mkdir -p .git/hooks &&
+	echo \#!/bin/sh > .git/hooks/pre-commit &&
+	echo echo Hello generic. >> .git/hooks/pre-commit &&
+	chmod u+x .git/hooks/pre-commit &&
+	echo \#!/bin/sh > .git/hooks/pre-commit_${expected_platform} &&
+	echo echo Hello ${expected_platform} >> .git/hooks/pre-commit_${expected_platform} &&
+	chmod u+x .git/hooks/pre-commit_${expected_platform} &&
+	echo test > README &&
+	git add README &&
+	git commit -am "1-2-3 this is a test." 2>out.txt &&
+	cat out.txt | grep Hello\ ${expected_platform}
+'
+
+if [ ${expected_platform} != "windows" ] ; then
+	# chmod does not work well on Windows.
+	test_expect_success 'set standard and native pre-commit hooks but let the native one not executable' '
+		mkdir -p test-repo &&
+		cd test-repo &&
+		git init &&
+		mkdir -p .git/hooks &&
+		echo \#!/bin/sh > .git/hooks/pre-commit &&
+		echo echo Hello generic. >> .git/hooks/pre-commit &&
+		chmod u+x .git/hooks/pre-commit &&
+		echo \#!/bin/sh > .git/hooks/pre-commit_${expected_platform} &&
+		echo echo Hello ${expected_platform} >> .git/hooks/pre-commit_${expected_platform} &&
+		echo test > README &&
+		git add README &&
+		git commit -am "1-2-3 this is a test." 2>out.txt &&
+		cat out.txt | grep Hello\ generic
+	'
+
+	test_expect_success 'set standard pre-commit hook only' '
+		mkdir -p test-repo &&
+		cd test-repo &&
+		git init &&
+		mkdir -p .git/hooks &&
+		echo \#!/bin/sh > .git/hooks/pre-commit &&
+		echo echo Hello standard hook. >> .git/hooks/pre-commit &&
+		chmod u+x .git/hooks/pre-commit &&
+		echo test > README &&
+		git add README &&
+		git commit -am "1-2-3 this is a test." 2>out.txt &&
+		cat out.txt | grep Hello\ standard\ hook
+	'
+fi
+
+test_done

base-commit: 225bc32a989d7a22fa6addafd4ce7dcd04675dbf
-- 
gitgitgadget

             reply	other threads:[~2021-08-21 20:00 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-21 20:00 Rafael Santiago via GitGitGadget [this message]
2021-08-21 21:50 ` [PATCH] Give support for hooks based on platform brian m. carlson
2021-08-21 23:11   ` Rafael Santiago
2021-08-22 22:07     ` brian m. carlson
2021-08-23  1:07       ` Rafael Santiago
2021-08-23 16:23       ` Jeff King
2021-08-23 17:59         ` Junio C Hamano
2021-08-23 18:32           ` Jeff King
2021-08-23 16:35       ` Junio C Hamano

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=pull.1069.git.git.1629576007891.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=voidbrainvoid@tutanota.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).