Skip to content

Commit

Permalink
Allow skipping hooks in certain git states: merge and/or rebase (#173)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrey Novikov <[email protected]>
  • Loading branch information
DmitryTsepelev and Envek authored May 26, 2021
1 parent 8defa7e commit 6b4f4ef
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 3 deletions.
20 changes: 19 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,32 @@ func getRootPath() string {
return rootPath
}

// Get absolute path to repository or worktree root
func setRootPath() {
// get absolute path to .git dir (project root)
cmd := exec.Command("git", "rev-parse", "--show-toplevel")

outputBytes, _ := cmd.CombinedOutput()
rootPath = strings.TrimSpace(string(outputBytes))
}

// Get absolute path to .git directory (or current worktree subdirectory in it)
func getGitDir() string {
cmd := exec.Command("git", "rev-parse", "--git-dir") // that may be relative

outputBytes, err := cmd.CombinedOutput()
if err != nil {
panic(err)
}

path := strings.TrimSpace(string(outputBytes))

if filepath.IsAbs(path) {
return path
}

return filepath.Join(getRootPath(), path)
}

func getGitHooksPath() string {
return gitHooksPath
}
Expand Down
65 changes: 63 additions & 2 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,73 @@ func isScriptExist(hooksGroup, executableName string) bool {

func isSkipScript(hooksGroup, executableName string) bool {
key := strings.Join([]string{hooksGroup, scriptsConfigKey, executableName, skipConfigKey}, ".")
return viper.GetBool(key)
return isSkip(key)
}

func isSkipCommand(hooksGroup, executableName string) bool {
key := strings.Join([]string{hooksGroup, commandsConfigKey, executableName, skipConfigKey}, ".")
return viper.GetBool(key)
return isSkip(key)
}

func isSkip(key string) bool {
value := viper.Get(key)

switch typedValue := value.(type) {
case bool:
/*
pre-push:
commands:
packages-audit:
skip: true
*/
return typedValue
case string:
/*
pre-push:
commands:
packages-audit:
skip: merge
*/
return isSkippedGitState(typedValue)
case []interface{}:
/*
pre-push:
commands:
packages-audit:
skip:
- merge
- rebase
*/
for _, gitState := range typedValue {
if isSkippedGitState(gitState.(string)) {
return true
}
}
}

return false
}

func isSkippedGitState(state string) bool {
return state == "merge" && isMergeInProgress() || state == "rebase" && isRebaseInProgress()
}

func isMergeInProgress() bool {
if _, err := os.Stat(filepath.Join(getGitDir(), "MERGE_HEAD")); os.IsNotExist(err) {
return false
}

return true
}

func isRebaseInProgress() bool {
if _, mergeErr := os.Stat(filepath.Join(getGitDir(), "rebase-merge")); os.IsNotExist(mergeErr) {
if _, applyErr := os.Stat(filepath.Join(getGitDir(), "rebase-apply")); os.IsNotExist(applyErr) {
return false
}
}

return true
}

// NOTE: confusing option, suppose it unnesecary and should be deleted.
Expand Down
20 changes: 20 additions & 0 deletions docs/full_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,26 @@ pre-push:
skip: true
```

## Skipping commands during rebase or merge

You can skip commands during rebase and/or merge by the same `skip` option:

```yml
pre-push:
commands:
packages-audit:
skip: merge
# or
pre-push:
commands:
packages-audit:
skip:
- merge
- rebase
```

## Skipping commands by tags

If we have a lot of commands and scripts we can tag them and run skip commands with a specific tag.
Expand Down

0 comments on commit 6b4f4ef

Please sign in to comment.