github.com/kcmvp/gob@v1.0.17/cmd/gbc/artifact/hook.go (about)

     1  package artifact
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"github.com/fatih/color"
     7  	"github.com/samber/lo"
     8  	"os"
     9  	"path/filepath"
    10  )
    11  
    12  const (
    13  	command    = "gbc"
    14  	execCfgKey = "exec"
    15  	//hook script name
    16  	CommitMsg = "commit-msg"
    17  	PreCommit = "pre-commit"
    18  	PrePush   = "pre-push"
    19  )
    20  
    21  func HookScripts() map[string]string {
    22  	return map[string]string{
    23  		CommitMsg: fmt.Sprintf("%s exec %s $1", command, CommitMsg),
    24  		PreCommit: fmt.Sprintf("%s exec %s", command, PreCommit),
    25  		PrePush:   fmt.Sprintf("%s exec %s $1 $2", command, PrePush),
    26  	}
    27  }
    28  
    29  type GitHook struct {
    30  	CommitMsg string   `mapstructure:"commit-msg"`
    31  	PreCommit []string `mapstructure:"pre-commit"`
    32  	PrePush   []string `mapstructure:"pre-push"`
    33  }
    34  
    35  func (project *Project) GitHook() GitHook {
    36  	var hook GitHook
    37  	project.load().UnmarshalKey(execCfgKey, &hook) //nolint
    38  	return hook
    39  }
    40  
    41  type Execution struct {
    42  	CmdKey  string
    43  	Actions []string
    44  }
    45  
    46  func (project *Project) Executions() []Execution {
    47  	values := project.load().Get(execCfgKey)
    48  	if values == nil {
    49  		return []Execution{}
    50  	}
    51  	return lo.MapToSlice(values.(map[string]any), func(key string, v any) Execution {
    52  		var actions []string
    53  		if _, ok := v.(string); ok {
    54  			actions = append(actions, v.(string))
    55  		} else {
    56  			actions = lo.Map(v.([]any), func(item any, _ int) string {
    57  				return fmt.Sprintf("%s", item)
    58  			})
    59  		}
    60  		return Execution{CmdKey: key, Actions: actions}
    61  	})
    62  }
    63  
    64  // SetupHooks setup git local hooks for project. force means always update gob.yaml
    65  func (project *Project) SetupHooks(force bool) error {
    66  	if force {
    67  		hook := map[string]any{
    68  			fmt.Sprintf("%s.%s", execCfgKey, CommitMsg): "^#[0-9]+:\\s*.{10,}$",
    69  			fmt.Sprintf("%s.%s", execCfgKey, PreCommit): []string{"lint", "test"},
    70  			fmt.Sprintf("%s.%s", execCfgKey, PrePush):   []string{"test"},
    71  		}
    72  		if err := project.mergeConfig(hook); err != nil {
    73  			color.Red("failed to setup hook")
    74  		}
    75  	}
    76  	if !InGit() {
    77  		color.Yellow("project is not in the source control")
    78  		return nil
    79  	}
    80  	// force load configuration again for testing
    81  	_ = project.load().ReadInConfig()
    82  	gitHook := CurProject().GitHook()
    83  	var hooks []string
    84  	if len(gitHook.CommitMsg) > 0 {
    85  		hooks = append(hooks, CommitMsg)
    86  	}
    87  	if len(gitHook.PreCommit) > 0 {
    88  		hooks = append(hooks, PreCommit)
    89  	}
    90  	if len(gitHook.PrePush) > 0 {
    91  		hooks = append(hooks, PrePush)
    92  	}
    93  	shell := lo.IfF(Windows(), func() string {
    94  		return "#!/usr/bin/env bash\n"
    95  	}).Else("#!/bin/sh\n")
    96  	hookDir := CurProject().HookDir()
    97  	for name, script := range HookScripts() {
    98  		if lo.Contains(hooks, name) || force {
    99  			msgHook, _ := os.OpenFile(filepath.Join(hookDir, name), os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm)
   100  			writer := bufio.NewWriter(msgHook)
   101  			writer.WriteString(shell)
   102  			writer.WriteString("\n")
   103  			writer.WriteString(script)
   104  			writer.Flush()
   105  			msgHook.Close()
   106  		} else {
   107  			os.Remove(filepath.Join(hookDir, name))
   108  		}
   109  	}
   110  	return nil
   111  }