Skip to content

Commit

Permalink
feat: Provide manual install mode (#124)
Browse files Browse the repository at this point in the history
- Now you can use `--use-manual` for the installer and Githooks will not set
  `init.templateDir` nor `core.hooksPath` and the user is responsible to install hooks into repositories
  by `git hooks install` which use Githooks.
  • Loading branch information
gabyx authored Jul 11, 2023
1 parent 7e23633 commit 64436be
Show file tree
Hide file tree
Showing 53 changed files with 494 additions and 158 deletions.
4 changes: 3 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ jobs:
description: "The test script name"
default: "test-alpine"
type: string
executor: win/server-2022
executor:
name: win/server-2022
version: 2023.04.1
steps:
- checkout
- run:
Expand Down
55 changes: 45 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -888,22 +888,38 @@ The installer will:
1. Launch the current (or new if `--update` is given) installer which proceeds
with the next steps.

1. Find out where the Git templates directory is.
1. Find the install mode relevant directory:

1. From the `$GIT_TEMPLATE_DIR` environment variable.
2. With the `git config --get init.templateDir` command.
3. Checking the default `/usr/share/git-core/templates` folder.
4. Search on the filesystem for matching directories.
5. Offer to set up a new one, and make it `init.templateDir`.
- For `Template Dir` install mode: Use the Git template directory

1. Write all chosen Githooks run-wrappers into the chosen directory:
1. from `--template-dir` if given or
1. from the `$GIT_TEMPLATE_DIR` environment variable or
1. use the `git config --get init.templateDir` or
1. use the Git default `/usr/share/git-core/templates` folder or
1. search on the file system for matching directories or
1. offer to set up a new one.

- either `init.templateDir` or
- `core.hooksPath` depending on the install mode `--use-core-hooks-path`.
- For `Centralized Hooks` install mode: Use the hooks directory

1. from `--template-dir` if given, or
1. use `git config --get core.hooksPath` command if set or
1. otherwise use `<install-dir>/templates`.

- For `Manual` install mode use the directory

1. from `--template-dir` if given or
1. otherwise use `<install-dir>/templates`.

1. Write all Githooks run-wrappers into the hooks directory and set

- either `init.templateDir` for `Normal` install mode or
- `core.hooksPath` for `Centralized Hooks` install mode
(`--use-core-hooks-path`) or
- `githooks.manualTemplateDir` for `Manual` install mode (`--use-manual`)

1. Offer to enable automatic update checks.

1. Offer to find existing Git repositories on the filesystem (disable with
1. Offer to find existing Git repositories on the file system (disable with
`--skip-install-into-existing`)

1. Install run-wrappers into them (`.git/hooks`).
Expand Down Expand Up @@ -967,6 +983,25 @@ curl -sL https://raw.githubusercontent.com/gabyx/githooks/main/scripts/install.s
--template-dir /home/public/.githooks
```

### Install Mode - Manual

You also have the option for none of the two above methods and to use Githooks
in _manual_ mode. This means that hook run wrappers are not injected by the
`init.templateDir` Git config setting into new cloned repositories, nor does it
set `core.hooksPath`. This means, you decide yourself when to use Githooks in a
repository simply by doing one of the following with the same effect:

- Run `git hooks install` or `git hooks uninstall` to install run wrappers
explicitly.
- Set `core.hooksPath` inside the repository you want to use Githooks with to
the template directory Githooks maintains, e.g.

```shell
git config core.hooksPath "$(git config githooks.templateDir)"
```

This also means that Githooks might not run if you forget to install the hooks.

### Install from different URL and Branch

If you want to install from another Git repository (e.g. from your own or your
Expand Down
1 change: 1 addition & 0 deletions docs/cli/git_hooks_installer.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ git hooks installer [flags]
- `server` : Only server hooks supported by Githooks.
You can list them separately or comma-separated in one argument.
--use-core-hookspath If the install mode `core.hooksPath` should be used.
--use-manual If the install mode `manual` should be used.
--clone-url string The clone url from which Githooks should clone
and install/update itself. Githooks tries to
auto-detect the deploy setting for downloading binaries.
Expand Down
64 changes: 64 additions & 0 deletions githooks/cmd/common/install/install-mode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package install

import (
"github.com/gabyx/githooks/githooks/git"
"github.com/gabyx/githooks/githooks/hooks"
)

type InstallModeType int
type installModeType struct {
None InstallModeType
TemplateDir InstallModeType
CoreHooksPath InstallModeType
Manual InstallModeType
}

// InstallModeTypeV enumerates all types of install modes.
var InstallModeTypeV = &installModeType{TemplateDir: 0, CoreHooksPath: 1, Manual: 2, None: 3} // nolint:gomnd

// GetInstallMode returns the current set install mode of Githooks.
func GetInstallMode(gitx *git.Context) InstallModeType {
useManual := gitx.GetConfig(hooks.GitCKUseManual, git.GlobalScope) == git.GitCVTrue
useCoreHooksPathValue := gitx.GetConfig(hooks.GitCKUseCoreHooksPath, git.GlobalScope)

switch {
case useManual:
return InstallModeTypeV.Manual
case useCoreHooksPathValue == git.GitCVTrue:
return InstallModeTypeV.CoreHooksPath
case useCoreHooksPathValue == git.GitCVFalse:
return InstallModeTypeV.TemplateDir
default:
return InstallModeTypeV.None
}

}

// GetInstallModeName returns a string for the install mode.
func GetInstallModeName(installMode InstallModeType) string {
switch installMode {
case InstallModeTypeV.Manual:
return "manual"
case InstallModeTypeV.TemplateDir:
return "template-dir"
case InstallModeTypeV.CoreHooksPath:
return "core-hooks-path"
default:
return "none"
}
}

// MapInstallerArgsToInstallMode maps installer arguments to install modes.
func MapInstallerArgsToInstallMode(
useCoreHooksPath bool,
useManual bool) InstallModeType {

switch {
case useManual:
return InstallModeTypeV.Manual
case useCoreHooksPath:
return InstallModeTypeV.CoreHooksPath
default:
return InstallModeTypeV.TemplateDir
}
}
59 changes: 37 additions & 22 deletions githooks/cmd/common/install/template-dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import (

cm "github.com/gabyx/githooks/githooks/common"
"github.com/gabyx/githooks/githooks/git"
"github.com/gabyx/githooks/githooks/hooks"
strs "github.com/gabyx/githooks/githooks/strings"
)

// CheckTemplateDir checks the target directory and if valid
// returns the target hook template directory otherwise empty.
// If an error occures the directory is empty.
// If an error occurs the directory is empty.
func CheckTemplateDir(targetDir string, subFolderIfExists string) (string, error) {
if strs.IsNotEmpty(targetDir) {

Expand All @@ -29,34 +30,48 @@ func CheckTemplateDir(targetDir string, subFolderIfExists string) (string, error
}

// FindHookTemplateDir finds the hook template directory.
func FindHookTemplateDir(gitx *git.Context, useCoreHooksPath bool) (hooksTemplateDir string, err error) {
// 1. Try setup from environment variables
gitTempDir, exists := os.LookupEnv("GIT_TEMPLATE_DIR")
if exists {
if hooksTemplateDir, err = CheckTemplateDir(gitTempDir, "hooks"); err != nil {
return
} else if strs.IsNotEmpty(hooksTemplateDir) {
return
}
}
// `init.templateDir` and `core.hooksPath` can already be
// set and controlled by the user.
func FindHookTemplateDir(gitx *git.Context, installMode InstallModeType) (hooksTemplateDir string, err error) {

switch installMode {
case InstallModeTypeV.Manual:

hooksTemplateDir, err = CheckTemplateDir(
gitx.GetConfig(hooks.GitCKManualTemplateDir, git.GlobalScope), "hooks")

case InstallModeTypeV.CoreHooksPath:

// 2. Try setup from git config
if useCoreHooksPath {
hooksTemplateDir, err = CheckTemplateDir(
gitx.GetConfig(git.GitCKCoreHooksPath, git.GlobalScope), "")
} else {

case InstallModeTypeV.None:
fallthrough
case InstallModeTypeV.TemplateDir:

// 1. Try setup from environment variables
gitTempDir, exists := os.LookupEnv("GIT_TEMPLATE_DIR")
if exists {
if hooksTemplateDir, err = CheckTemplateDir(gitTempDir, "hooks"); err != nil {
return
} else if strs.IsNotEmpty(hooksTemplateDir) {
return
}
}

// 2. Try setup from git config
hooksTemplateDir, err = CheckTemplateDir(
gitx.GetConfig(git.GitCKInitTemplateDir, git.GlobalScope), "hooks")
}

if err != nil {
return
} else if strs.IsNotEmpty(hooksTemplateDir) {
return
}
if err != nil {
return
} else if strs.IsNotEmpty(hooksTemplateDir) {
return
}

// 3. Try setup from the default location
hooksTemplateDir, err = CheckTemplateDir(path.Join(git.GetDefaultTemplateDir(), "hooks"), "")
// 3. Try setup from the default location
hooksTemplateDir, err = CheckTemplateDir(path.Join(git.GetDefaultTemplateDir(), "hooks"), "")
}

return
}
3 changes: 2 additions & 1 deletion githooks/cmd/installer/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ type Arguments struct {

MaintainedHooks []string // Maintain hooks by Githooks.

UseCoreHooksPath bool // Use the `core.hooksPath` for the template dir.
UseCoreHooksPath bool // Use install mode: `core.hooksPath` for the template dir.
UseManual bool // Use install mode: manual -> no `core.hooksPath` nor `init.templateDir`

InstallPrefix string // Install prefix for Githooks.
TemplateDir string // Template dir to use for the hooks.
Expand Down
Loading

0 comments on commit 64436be

Please sign in to comment.