Skip to content

Commit

Permalink
Merge pull request #20 from gabyx/feature/provide-os-arch-substituion
Browse files Browse the repository at this point in the history
Make `GITHOOKS_OS` and `GITHOOKS_ARCH` available in hooks
  • Loading branch information
gabyx authored Apr 26, 2021
2 parents 3ddcaaf + 0c87837 commit 700d099
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 15 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Also it searches for hooks in configured shared hook repositories.
- [Layout and Options](#layout-and-options)
- [Execution](#execution)
- [Hook Run Configuration](#hook-run-configuration)
- [Exported Environment Variables](#exported-environment-variables)
- [Parallel Execution](#parallel-execution)
- [Supported Hooks](#supported-hooks)
- [Git Large File Storage Git LFS Support](#git-large-file-storage-git-lfs-support)
Expand Down Expand Up @@ -78,6 +79,7 @@ Also it searches for hooks in configured shared hook repositories.
- [Todos:](#todos)
- [Acknowledgements](#acknowledgements)
- [Authors](#authors)
- [Support & Donation](#support--donation)
- [License](#license)

<!-- /TOC -->
Expand Down Expand Up @@ -199,6 +201,14 @@ Escaping the above syntax works with `\${...}`.
The reason is that each hook invocation by Git is separate. Avoiding reading this total file several times
needs time and since we want speed and only an opt-in solution this is avoided.

### Exported Environment Variables

Githooks defines the following environment variables:

- `STAGED_FILES` : All staged files, applicable to hooks: `pre-commit`, `prepare-commit-msg` and `commit-msg`.
- `GITHOOKS_OS` : The runtime operating system, applicable to all hooks. [See this list](https://github.com/golang/go/blob/master/src/go/build/syslist.go).
- `GITHOOKS_ARCH` : The runtime operating architecture, applicable to all hooks. [See this list](https://github.com/golang/go/blob/master/src/go/build/syslist.go).

### Parallel Execution

As in the [example](#layout-and-options), all discovered hooks in subfolders `<batchName>`, e.g. `<repoPath>/<hooksDir>/<hookName>/<batchName>/*` where `<hooksDir>` is either
Expand Down
2 changes: 1 addition & 1 deletion githooks/apps/dialog/cmd/common/flags-opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (i *indexArgs) Set(s string) error {

value, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return cm.Error("Could not parse index '%s'.", s)
return cm.ErrorF("Could not parse index '%s'.", s)
}

*i.indices = append(*i.indices, uint(value))
Expand Down
6 changes: 6 additions & 0 deletions githooks/apps/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func mainRun() (exitCode int) {
return
}

exportGeneralEnvVars()
exportStagedFiles(&settings)
updateGithooks(&settings, &uiSettings)
executeLFSHooks(&settings)
Expand Down Expand Up @@ -251,6 +252,11 @@ func showTrustRepoPrompt(gitx *git.Context, promptCtx prompt.IContext) (isTruste
return
}

func exportGeneralEnvVars() {
os.Setenv(hooks.EnvVariableOs, runtime.GOOS)
os.Setenv(hooks.EnvVariableArch, runtime.GOARCH)
}

func exportStagedFiles(settings *HookSettings) {
if strs.Includes(hooks.StagedFilesHookNames[:], settings.HookName) {

Expand Down
4 changes: 2 additions & 2 deletions githooks/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func Build(repoPath string, buildTags []string) (string, error) {

goSrc := path.Join(repoPath, relPathGoSrc)
if !cm.IsDirectory(goSrc) {
return "", cm.Error("Source directors '%s' is not existing.", goSrc)
return "", cm.ErrorF("Source directors '%s' is not existing.", goSrc)
}

goPath := path.Join(repoPath, relPathGoSrc, ".go")
Expand All @@ -105,7 +105,7 @@ func Build(repoPath string, buildTags []string) (string, error) {
e1 := os.RemoveAll(goPath)
e2 := os.RemoveAll(goBinPath)
if e1 != nil || e2 != nil {
return goBinPath, cm.ErrorF("Could not remove temporary build files.")
return goBinPath, cm.Error("Could not remove temporary build files.")
}

// Set working dir.
Expand Down
22 changes: 20 additions & 2 deletions githooks/git/gitcommon.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,13 @@ func FindGitDirs(searchDir string) (all []string, err error) {

// Clone an URL to a path `repoPath`.
func Clone(repoPath string, url string, branch string, depth int) error {
args := []string{"clone", "-c", "core.hooksPath=", "--template=", "--single-branch"}
// Its important to not use any template directory here to not
// install accidentally Githooks run-wrappers.
// We set the `core.hooksPath` explicitly to its internal hooks directory to not interfer
// with global settings.
// Also this installs LFS hooks, which comes handy for certain shared hook repos
// with prebuilt binaries.
args := []string{"clone", "-c", "core.hooksPath=.git/hooks", "--template=", "--single-branch"}

if branch != "" {
args = append(args, "--branch", branch)
Expand All @@ -247,7 +253,19 @@ func Clone(repoPath string, url string, branch string, depth int) error {
}

args = append(args, []string{url, repoPath}...)
out, e := CtxSanitized().GetCombined(args...)

ctx := CtxSanitized()
// We must not execute this clone command inside a Git repo (e.g. A)
// due to `core.hooksPath=.git/hooks` which get applied to `A` -> Bug ?:
// https://stackoverflow.com/questions/67273420/why-does-git-execute-hooks-from-an-other-repository
ctx.Cwd = path.Dir(repoPath)
if !cm.IsDirectory(ctx.Cwd) {
if e := os.MkdirAll(ctx.Cwd, cm.DefaultFileModeDirectory); e != nil {
return cm.ErrorF("Could not create working directory '%s'.", ctx.Cwd)
}
}

out, e := ctx.GetCombined(args...)

if e != nil {
return cm.ErrorF("Cloning of '%s' [branch: '%s']\ninto '%s' failed:\n%s", url, branch, repoPath, out)
Expand Down
6 changes: 6 additions & 0 deletions githooks/hooks/githooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ var LFSHookNames = [4]string{
// StagedFilesHookNames are the hook names on which staged files are exported.
var StagedFilesHookNames = [3]string{"pre-commit", "prepare-commit-msg", "commit-msg"}

// EnvVariableOs is the environment variable which holds runtime operating system name.
const EnvVariableOs = "GITHOOKS_OS"

// EnvVariableArch is the environment variable which holds runtime architecture name.
const EnvVariableArch = "GITHOOKS_ARCH"

// EnvVariableStagedFiles is the environment variable which holds the staged files.
const EnvVariableStagedFiles = "STAGED_FILES"

Expand Down
8 changes: 4 additions & 4 deletions githooks/hooks/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ func GetHookRunCmd(hookPath string, args []string) (exec cm.Executable, err erro
return
}

subst := getEnvSubstitution(os.LookupEnv, git.Ctx().LookupConfig)
subst := getVarSubstitution(os.LookupEnv, git.Ctx().LookupConfig)

if exec.Cmd, err = subst(config.Cmd); err != nil {
err = cm.CombineErrors(err,
cm.Error("Error in hook run config '%s'.", hookPath))
cm.ErrorF("Error in hook run config '%s'.", hookPath))

return
}
Expand All @@ -77,7 +77,7 @@ func GetHookRunCmd(hookPath string, args []string) (exec cm.Executable, err erro
for i := range config.Args {
if exec.Args[i], err = subst(exec.Args[i]); err != nil {
err = cm.CombineErrors(err,
cm.Error("Error in hook run config '%s'.", hookPath))
cm.ErrorF("Error in hook run config '%s'.", hookPath))

return
}
Expand All @@ -90,7 +90,7 @@ func GetHookRunCmd(hookPath string, args []string) (exec cm.Executable, err erro

var reEnvVariable = regexp.MustCompile(`(\\?)\$\{(!?)(env|git|git-l|git-g|git-s):([a-zA-Z.][a-zA-Z0-9_.]+)\}`)

func getEnvSubstitution(
func getVarSubstitution(
getEnv func(string) (string, bool),
gitGet func(string, git.ConfigScope) (string, bool)) func(string) (string, error) {

Expand Down
2 changes: 1 addition & 1 deletion githooks/hooks/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func getGitConfig(key string, scope git.ConfigScope) (string, bool) {

func TestEnvReplace(t *testing.T) {

subst := getEnvSubstitution(os.LookupEnv, getGitConfig)
subst := getVarSubstitution(os.LookupEnv, getGitConfig)

os.Setenv("var", "banana")
os.Setenv("tar", "monkey")
Expand Down
2 changes: 1 addition & 1 deletion githooks/updates/download/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (s *LocalDeploySettings) Download(versionTag string, dir string) error {
case strings.HasSuffix(targetFile, ".zip"):
targetExtension = ".zip"
default:
return cm.Error("Archive type of file '%s' not supporeted.", targetFile)
return cm.ErrorF("Archive type of file '%s' not supporeted.", targetFile)
}

targetDir := path.Dir(targetFile)
Expand Down
13 changes: 12 additions & 1 deletion tests/step-012.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,18 @@ mkdir -p "$GH_TEST_TMP/test12" &&

mkdir -p .githooks &&
echo "echo 'Direct execution' > '$GH_TEST_TMP/test012.out'" >.githooks/pre-commit &&
echo "echo \"\$GITHOOKS_OS\" > '$GH_TEST_TMP/test012env.out'" >>.githooks/pre-commit &&
echo "echo \"\$GITHOOKS_ARCH\" >> '$GH_TEST_TMP/test012env.out'" >>.githooks/pre-commit &&
"$GH_TEST_BIN/runner" "$(pwd)"/.git/hooks/pre-commit ||
exit 1

grep -q 'Direct execution' "$GH_TEST_TMP/test012.out"
# From https://github.com/golang/go/blob/master/src/go/build/syslist.go
goosList="aix|android|darwin|dragonfly|freebsd|hurd|illumos|ios|js|linux|nacl|netbsd|openbsd|plan9|solaris|windows|zos"
goarchList="386|amd64|amd64p32|arm|armbe|arm64|arm64be|ppc64|ppc64le|mips|mipsle|mips64|mips64le|mips64p32|mips64p32le|ppc|riscv|riscv64|s390|s390x|sparc|sparc64|wasm"

if ! grep -q 'Direct execution' "$GH_TEST_TMP/test012.out" ||
! grep -Eq "$goosList" "$GH_TEST_TMP/test012env.out" ||
! grep -Eq "$goarchList" "$GH_TEST_TMP/test012env.out"; then
echo "! Expected GITHOOKS_OS and GITHOOKS_ARCH to be defined."
exit 4
fi
6 changes: 3 additions & 3 deletions tests/step-061.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ acceptAllTrustPrompts || exit 1
mkdir -p "$GH_TEST_TMP/shared/first-shared.git/pre-commit" &&
cd "$GH_TEST_TMP/shared/first-shared.git" &&
echo 'echo "Hello"' >pre-commit/sample-one &&
git init --template=/dev/null && git add . && git commit -m 'Testing' || exit 1
git init --template= && git add . && git commit -m 'Testing' || exit 1

mkdir -p "$GH_TEST_TMP/shared/second-shared.git/pre-commit" &&
cd "$GH_TEST_TMP/shared/second-shared.git" &&
echo 'echo "Hello"' >pre-commit/sample-two &&
git init --template=/dev/null && git add . && git commit -m 'Testing' || exit 1
git init --template= && git add . && git commit -m 'Testing' || exit 1

mkdir -p "$GH_TEST_TMP/shared/third-shared.git/pre-commit" &&
cd "$GH_TEST_TMP/shared/third-shared.git" &&
echo 'echo "Hello"' >pre-commit/sample-three &&
git init --template=/dev/null && git add . && git commit -m 'Testing' || exit 1
git init --template= && git add . && git commit -m 'Testing' || exit 1

mkdir -p "$GH_TEST_TMP/test061/.githooks" &&
cd "$GH_TEST_TMP/test061" &&
Expand Down
19 changes: 19 additions & 0 deletions tests/step-121.sh
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ if [ "$?" -ne 0 ] ||
exit 6
fi

# Testing "!" operator.
# Test if it fails!
cat <<"EOF" >".githooks/pre-commit.yaml" || exit 5
cmd: "${env:GH_TEST_TMP}/test121/custom-runner.exe"
Expand All @@ -115,3 +116,21 @@ if [ "$?" -eq 0 ] || ! echo "$OUT" | grep "Error in hook run config"; then
echo "! Expected hook to fail."
exit 7
fi

# Testing GITHOOKS_OS/GITHOOKS_ARCH
# Test if it does not fail!
cat <<"EOF" >".githooks/pre-commit.yaml" || exit 5
cmd: "${env:GH_TEST_TMP}/test121/custom-runner.exe"
args:
- "my-file.py"
- "${!env:GITHOOKS_OS}"
- "${!env:GITHOOKS_ARCH}"
version: 1
EOF

OUT=$("$GH_TEST_BIN/runner" "$(pwd)"/.git/hooks/pre-commit 2>&1)
# shellcheck disable=SC2181,SC2016
if [ "$?" -ne 0 ] || echo "$OUT" | grep "Error in hook run config"; then
echo "! Expected hook to succeed."
exit 8
fi

0 comments on commit 700d099

Please sign in to comment.