Skip to content

Commit

Permalink
fix: support whitespaces in directory names for scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexox committed Sep 20, 2024
1 parent 76cf1a0 commit 1064edc
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 39 deletions.
9 changes: 5 additions & 4 deletions internal/git/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,19 @@ var refBranchRegexp = regexp.MustCompile(`^ref:\s*refs/heads/(.+)$`)

func (r *Repository) State() State {
branch := r.Branch()
if r.isMergeState() {
if r.inMergeState() {
return State{
Branch: branch,
Step: MergeStep,
}
}
if r.isRebaseState() {
if r.inRebaseState() {
return State{
Branch: branch,
Step: RebaseStep,
}
}

return State{
Branch: branch,
Step: NilStep,
Expand Down Expand Up @@ -65,14 +66,14 @@ func (r *Repository) Branch() string {
return ""
}

func (r *Repository) isMergeState() bool {
func (r *Repository) inMergeState() bool {
if _, err := r.Fs.Stat(filepath.Join(r.GitPath, "MERGE_HEAD")); os.IsNotExist(err) {
return false
}
return true
}

func (r *Repository) isRebaseState() bool {
func (r *Repository) inRebaseState() bool {
if _, mergeErr := r.Fs.Stat(filepath.Join(r.GitPath, "rebase-merge")); os.IsNotExist(mergeErr) {
if _, applyErr := r.Fs.Stat(filepath.Join(r.GitPath, "rebase-apply")); os.IsNotExist(applyErr) {
return false
Expand Down
4 changes: 2 additions & 2 deletions internal/lefthook/runner/exec/execute_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ func (e CommandExecutor) Execute(ctx context.Context, opts Options, in io.Reader
return nil
}

func (e CommandExecutor) execute(ctx context.Context, cmdstr string, args *executeArgs) error {
command := exec.CommandContext(ctx, "sh", "-c", cmdstr)
func (e CommandExecutor) execute(ctx context.Context, cmd []string, args *executeArgs) error {
command := exec.CommandContext(ctx, "sh", "-c", strings.Join(cmd, " "))
command.Dir = args.root
command.Env = append(os.Environ(), args.envs...)

Expand Down
2 changes: 1 addition & 1 deletion internal/lefthook/runner/exec/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
// Options contains the data that controls the execution.
type Options struct {
Name, Root string
Commands []string
Commands [][]string
Env map[string]string
Interactive, UseStdin bool
}
Expand Down
8 changes: 4 additions & 4 deletions internal/lefthook/runner/prepare_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// An object that describes the single command's run option.
type run struct {
commands []string
commands [][]string
files []string
}

Expand Down Expand Up @@ -205,7 +205,7 @@ func escapeFiles(files []string) []string {
func replaceInChunks(str string, templates map[string]*template, maxlen int) *run {
if len(templates) == 0 {
return &run{
commands: []string{str},
commands: [][]string{strings.Split(str, " ")},
}
}

Expand All @@ -230,7 +230,7 @@ func replaceInChunks(str string, templates map[string]*template, maxlen int) *ru
}

var exhausted int
commands := make([]string, 0)
commands := make([][]string, 0)
for {
command := str
for name, template := range templates {
Expand All @@ -244,7 +244,7 @@ func replaceInChunks(str string, templates map[string]*template, maxlen int) *ru
}

log.Debug("[lefthook] executing: ", command)
commands = append(commands, command)
commands = append(commands, strings.Split(command, " "))
if exhausted >= len(templates) {
break
}
Expand Down
37 changes: 19 additions & 18 deletions internal/lefthook/runner/prepare_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runner

import (
"fmt"
"slices"
"testing"
)

Expand Down Expand Up @@ -103,7 +104,7 @@ func TestReplaceInChunks(t *testing.T) {
},
maxlen: 300,
res: &run{
commands: []string{"echo file1 file2 file3"},
commands: [][]string{{"echo", "file1", "file2", "file3"}},
files: []string{"file1", "file2", "file3"},
},
},
Expand All @@ -117,10 +118,10 @@ func TestReplaceInChunks(t *testing.T) {
},
maxlen: 10,
res: &run{
commands: []string{
"echo file1",
"echo file2",
"echo file3",
commands: [][]string{
{"echo", "file1"},
{"echo", "file2"},
{"echo", "file3"},
},
files: []string{"file1", "file2", "file3"},
},
Expand All @@ -135,9 +136,9 @@ func TestReplaceInChunks(t *testing.T) {
},
maxlen: 49, // (49 - 17(len of command without templates)) / 2 = 16, but we need 17 (3 words + 2 spaces)
res: &run{
commands: []string{
"echo file1 file2 && git add file1 file2",
"echo file3 && git add file3",
commands: [][]string{
{"echo", "file1", "file2", "&&", "git", "add", "file1", "file2"},
{"echo", "file3", "&&", "git", "add", "file3"},
},
files: []string{"file1", "file2", "file3"},
},
Expand All @@ -152,8 +153,8 @@ func TestReplaceInChunks(t *testing.T) {
},
maxlen: 51,
res: &run{
commands: []string{
"echo file1 file2 file3 && git add file1 file2 file3",
commands: [][]string{
{"echo", "file1", "file2", "file3", "&&", "git", "add", "file1", "file2", "file3"},
},
files: []string{"file1", "file2", "file3"},
},
Expand All @@ -172,9 +173,9 @@ func TestReplaceInChunks(t *testing.T) {
},
maxlen: 10,
res: &run{
commands: []string{
"echo push-file && git add file1",
"echo push-file && git add file2",
commands: [][]string{
{"echo", "push-file", "&&", "git", "add", "file1"},
{"echo", "push-file", "&&", "git", "add", "file2"},
},
files: []string{"push-file", "file1", "file2"},
},
Expand All @@ -193,10 +194,10 @@ func TestReplaceInChunks(t *testing.T) {
},
maxlen: 27,
res: &run{
commands: []string{
"echo push1 && git add file1",
"echo push2 && git add file2",
"echo push3 && git add file2",
commands: [][]string{
{"echo", "push1", "&&", "git", "add", "file1"},
{"echo", "push2", "&&", "git", "add", "file2"},
{"echo", "push3", "&&", "git", "add", "file2"},
},
files: []string{"push1", "push2", "push3", "file1", "file2"},
},
Expand All @@ -212,7 +213,7 @@ func TestReplaceInChunks(t *testing.T) {
t.Errorf("expected commands to be %d instead of %d", len(tt.res.commands), len(res.commands))
} else {
for i, command := range res.commands {
if command != tt.res.commands[i] {
if !slices.Equal(command, tt.res.commands[i]) {
t.Errorf("expected command %v to be equal to %v", command, tt.res.commands[i])
}
}
Expand Down
13 changes: 6 additions & 7 deletions internal/lefthook/runner/prepare_script.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,31 @@ package runner

import (
"os"
"strings"

"github.com/evilmartians/lefthook/internal/config"
"github.com/evilmartians/lefthook/internal/log"
)

func (r *Runner) prepareScript(script *config.Script, path string, file os.FileInfo) (string, error) {
func (r *Runner) prepareScript(script *config.Script, path string, file os.FileInfo) ([]string, error) {
if script.DoSkip(r.Repo.State()) {
return "", &skipError{"settings"}
return nil, &skipError{"settings"}
}

if intersect(r.Hook.ExcludeTags, script.Tags) {
return "", &skipError{"excluded tags"}
return nil, &skipError{"excluded tags"}
}

// Skip non-regular files (dirs, symlinks, sockets, etc.)
if !file.Mode().IsRegular() {
log.Debugf("[lefthook] file %s is not a regular file, skipping", file.Name())
return "", &skipError{"not a regular file"}
return nil, &skipError{"not a regular file"}
}

// Make sure file is executable
if (file.Mode() & executableMask) == 0 {
if err := r.Repo.Fs.Chmod(path, executableFileMode); err != nil {
log.Errorf("Couldn't change file mode to make file executable: %s", err)
return "", err
return nil, err
}
}

Expand All @@ -39,5 +38,5 @@ func (r *Runner) prepareScript(script *config.Script, path string, file os.FileI
args = append(args, path)
args = append(args, r.GitArgs...)

return strings.Join(args, " "), nil
return args, nil
}
2 changes: 1 addition & 1 deletion internal/lefthook/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func (r *Runner) runScript(ctx context.Context, script *config.Script, path stri
ok := r.run(ctx, exec.Options{
Name: file.Name(),
Root: r.Repo.RootPath,
Commands: []string{command},
Commands: [][]string{command},
Interactive: script.Interactive && !r.DisableTTY,
UseStdin: script.UseStdin,
Env: script.Env,
Expand Down
4 changes: 2 additions & 2 deletions internal/lefthook/runner/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ type (
)

func (e executor) Execute(_ctx context.Context, opts exec.Options, _in io.Reader, _out io.Writer) (err error) {
if strings.HasPrefix(opts.Commands[0], "success") {
if strings.HasPrefix(opts.Commands[0][0], "success") {
err = nil
} else {
err = errors.New(opts.Commands[0])
err = errors.New(opts.Commands[0][0])
}

return
Expand Down

0 comments on commit 1064edc

Please sign in to comment.