Skip to content

Commit

Permalink
🚧 Write hook message to file
Browse files Browse the repository at this point in the history
Write hook message to file that can be read by Git.
  • Loading branch information
mikelorant committed Feb 17, 2023
1 parent f105611 commit b7de666
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 21 deletions.
55 changes: 49 additions & 6 deletions internal/repository/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,49 @@ package repository

import (
"fmt"
"io"
"os"
)

type Commit struct {
Author string
Subject string
Body string
Footer string
Amend bool
DryRun bool
Author string
Subject string
Body string
Footer string
Amend bool
DryRun bool
Hook bool
MessageFile string
}

const command = "git"

func (r *Repository) Apply(c Commit) error {
if c.Hook {
return r.hook(c)
}

if err := r.Runner(os.Stdout, command, build(c)); err != nil {
return fmt.Errorf("unable to run command: %w", err)
}

return nil
}

func (r *Repository) hook(c Commit) error {
fh, err := r.OpenFiler(c.MessageFile, os.O_RDWR|os.O_TRUNC, 0o0755)
if err != nil {
return fmt.Errorf("unble to open file: %w", err)
}

err = write(c, fh)
if err != nil {
return fmt.Errorf("unable to write file: %w", err)
}

return nil
}

func build(c Commit) []string {
var args []string

Expand All @@ -49,3 +70,25 @@ func build(c Commit) []string {

return args
}

func write(c Commit, w io.WriteCloser) error {
var err error

fmt.Fprintln(w, c.Subject)
fmt.Fprintln(w, "")

if c.Body != "" {
fmt.Fprintln(w, c.Body)
fmt.Fprintln(w, "")
}

if c.Footer != "" {
fmt.Fprintln(w, c.Footer)
}

if err = w.Close(); err != nil {
return fmt.Errorf("unable to close file: %w", err)
}

return nil
}
165 changes: 150 additions & 15 deletions internal/repository/commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package repository_test
import (
"errors"
"io"
"os"
"strings"
"testing"

"github.com/mikelorant/committed/internal/repository"
Expand All @@ -29,21 +31,52 @@ func (r *MockShell) Run() func(w io.Writer, command string, args []string) error
}
}

type MockOpenFile struct {
filename string
mockFilename string
err error
close bool
}

func (o *MockOpenFile) OpenFile() func(string, int, os.FileMode) (*os.File, error) {
return func(filename string, flag int, perm os.FileMode) (*os.File, error) {
if o.err != nil {
return nil, o.err
}

fh, _ := os.CreateTemp("", "")

o.filename = filename
o.mockFilename = fh.Name()

if o.close {
fh.Close()
}

return fh, nil
}
}

var errMock = errors.New("error")

func TestApply(t *testing.T) {
t.Parallel()

type args struct {
commit repository.Commit
opts []func(c *repository.Commit)
err error
commit repository.Commit
opts []func(c *repository.Commit)
filename string
runErr error
openFileErr error
close bool
}

type want struct {
cmd string
args []string
err error
cmd string
args []string
data string
mockFilename string
err string
}

tests := []struct {
Expand Down Expand Up @@ -149,12 +182,100 @@ func TestApply(t *testing.T) {
},
},
{
name: "error",
name: "hook",
args: args{
commit: repository.Commit{
Hook: true,
MessageFile: "test",
},
},
want: want{
mockFilename: "test",
},
},
{
name: "hook_summary",
args: args{
commit: repository.Commit{
Subject: "summary",
Hook: true,
},
},
want: want{
data: "summary",
},
},
{
name: "hook_summary_body",
args: args{
commit: repository.Commit{
Subject: "summary",
Body: "body",
Hook: true,
},
},
want: want{
data: "summary\n\nbody",
},
},
{
name: "hook_summary_footer",
args: args{
commit: repository.Commit{
Subject: "summary",
Footer: "Signed-off-by: John Doe <[email protected]>",
Hook: true,
},
},
want: want{
data: "summary\n\nSigned-off-by: John Doe <[email protected]>",
},
},
{
name: "hook_summary_body_footer",
args: args{
commit: repository.Commit{
Subject: "summary",
Body: "body",
Footer: "Signed-off-by: John Doe <[email protected]>",
Hook: true,
},
},
want: want{
data: "summary\n\nbody\n\nSigned-off-by: John Doe <[email protected]>",
},
},
{
name: "run_error",
args: args{
runErr: errMock,
},
want: want{
err: "unable to run command: error",
},
},
{
name: "hook_error",
args: args{
commit: repository.Commit{
Hook: true,
},
openFileErr: errMock,
},
want: want{
err: "unble to open file: error",
},
},
{
name: "hook_error_close",
args: args{
err: errMock,
commit: repository.Commit{
Hook: true,
},
close: true,
},
want: want{
err: errMock,
err: "unable to write file: unable to close file: close",
},
},
}
Expand All @@ -165,23 +286,37 @@ func TestApply(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

var repo repository.Repository

shell := MockShell{
err: tt.want.err,
err: tt.args.runErr,
}

repo.Runner = shell.Run()
openFile := MockOpenFile{
filename: tt.args.filename,
err: tt.args.openFileErr,
close: tt.args.close,
}

repo := repository.Repository{
Runner: shell.Run(),
OpenFiler: openFile.OpenFile(),
}

err := repo.Apply(tt.args.commit)
if tt.want.err != nil {
if tt.want.err != "" {
assert.NotNil(t, err)
assert.ErrorContains(t, err, tt.want.err.Error())
assert.ErrorContains(t, err, tt.want.err)
return
}
assert.Nil(t, err)

assert.Equal(t, tt.want.cmd, shell.command)
assert.Equal(t, tt.want.args, shell.args)

if tt.args.commit.Hook {
out, _ := os.ReadFile(openFile.mockFilename)
assert.Equal(t, tt.want.mockFilename, openFile.filename)
assert.Equal(t, tt.want.data, strings.TrimSpace(string(out)))
}
})
}
}
3 changes: 3 additions & 0 deletions internal/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
"os"

"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
Expand Down Expand Up @@ -40,6 +41,7 @@ type Worktreer interface {
type Repository struct {
Opener func(string, *git.PlainOpenOptions) (*git.Repository, error)
Runner func(io.Writer, string, []string) error
OpenFiler func(string, int, os.FileMode) (*os.File, error)
GlobalConfig func(config.Scope) (*config.Config, error)
Configer Configer
Remoter Remoter
Expand All @@ -62,6 +64,7 @@ func New() *Repository {
return &Repository{
GlobalConfig: config.LoadConfig,
Opener: git.PlainOpenWithOptions,
OpenFiler: os.OpenFile,
Runner: shell.Run,
}
}
Expand Down

0 comments on commit b7de666

Please sign in to comment.