Skip to content

Commit

Permalink
update diff generation
Browse files Browse the repository at this point in the history
  • Loading branch information
mesuutt committed Jun 24, 2023
1 parent 87edb08 commit a2d7a2a
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 61 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/mesuutt/git-mirror
go 1.19

require (
github.com/stretchr/testify v1.8.1
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.25.3
)

Expand All @@ -14,6 +14,7 @@ require (
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY=
Expand Down
21 changes: 18 additions & 3 deletions internal/command/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"fmt"
"path/filepath"
"strings"
"time"

"github.com/urfave/cli/v2"

"github.com/mesuutt/git-mirror/pkg/commit"
"github.com/mesuutt/git-mirror/pkg/config"
"github.com/mesuutt/git-mirror/pkg/git"
"github.com/mesuutt/git-mirror/pkg/repo"
)
Expand Down Expand Up @@ -59,13 +61,20 @@ func AddCmdAction(ctx *cli.Context) error {

stats, err := parser.Parse(bytes.NewReader(out))
if err != nil {
return fmt.Errorf("diff output parse failed with error: `%v`", err)
return fmt.Errorf("diff output parse failed with error: `%w`", err)
}

if len(stats) == 0 {
return nil
}

commitGen := commit.NewDiffGenerator(filepath.Join(statRepoPath, "config.toml"))
conf, err := config.ReadConfig(filepath.Join(statRepoPath, "config.toml"))
if err != nil {
// print error and continue with defaults when cannot read config file.
fmt.Println(err)
}

commitGen := commit.NewDiffGenerator(conf)

var repoImpl repo.Repo
if dryRun {
Expand All @@ -76,7 +85,13 @@ func AddCmdAction(ctx *cli.Context) error {

// TODO: ignore already added commit
// if user run add multiple times without new commit, it should add only one commit to repo
if err := repoImpl.AddStats(commitGen.GenDiff(stats)); err != nil {
// maybe we can add commit hast to commit message, and check it at next commit
diff, err := commitGen.GenDiff(stats, commit.CommitInfo{Time: time.Now()})
if err != nil {
return err
}

if err := repoImpl.AddStats(diff); err != nil {
return err
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/commit/commit.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package commit

type Commit struct {
Filename string
Message string
import "time"

type CommitInfo struct {
Time time.Time
Hash string
}
74 changes: 32 additions & 42 deletions pkg/commit/diffgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,73 +11,64 @@ import (
"github.com/mesuutt/git-mirror/pkg/config"
)

const defaultCommitFormat = "%d insertion(s), %d deletion(s)"
const defaultLogMsgFormat = "%d insertion(s), %d deletion(s)"

type diffGen struct {
conf *config.Config
}

func NewDiffGenerator(configPath string) diffGen {
conf, err := config.ReadConfig(configPath)
if err != nil {
return diffGen{conf: nil}
}

func NewDiffGenerator(conf *config.Config) diffGen {
return diffGen{conf: conf}
}

func (f diffGen) GenDiff(stats []FileStat) Diff {
func (f diffGen) GenDiff(stats []FileStat, commitInfo CommitInfo) (*Diff, error) {
var diff Diff
dayParts := strings.Split(time.Now().Format("2006-01-02"), "-")
for _, stat := range stats {
ext := f.findExtensionAlias(stat.Ext)
filename := fmt.Sprintf("log.%s", ext)
fileExt := f.decideFileExtension(f.clearDot(stat.Ext))
filename := fmt.Sprintf("log.%s", fileExt)

// handle files without extension. eg: Makefile, Dockerfile etc
if !strings.HasPrefix(stat.Ext, ".") {
filename = stat.Ext
}

msg, err := f.buildMessage(&stat, ext)
text, err := f.generateLog(&stat, fileExt, commitInfo)
if err != nil {
panic("TODO")
return nil, fmt.Errorf("log text generation failed, err: %w", err)
}

diff.Changes = append(diff.Changes, Change{
Dir: filepath.Join(dayParts[0], dayParts[1], dayParts[2]),
Filename: filename,
Text: msg,
Text: text,
Insertion: stat.Insert,
Deletion: stat.Delete,
})
}

return diff
return &diff, nil
}

func (f diffGen) buildMessage(stat *FileStat, ext string) (string, error) {
func (f diffGen) generateLog(stat *FileStat, fileExt string, commitInfo CommitInfo) (string, error) {
if f.conf == nil {
return fmt.Sprintf(defaultCommitFormat, stat.Insert, stat.Delete), nil
return fmt.Sprintf(defaultLogMsgFormat, stat.Insert, stat.Delete), nil
}

// TODO: move template.New to init or once.Do
commitTempl, err := template.New("test").Parse(f.conf.Commit.Template)
// TODO: we can move template.New to constructor, init or once.Do
commitTemplate, err := template.New("log").Parse(f.conf.Commit.Template)
if err != nil {
return "", err
}

var commitMessage bytes.Buffer
fileExt := f.removeDot(ext)
now := time.Now() // TODO: get commit time instead now(usable especially with --dry-run)

commonVars := struct {
HM string
Hour string
Minute string
}{
HM: now.Format("15:04"),
Hour: now.Format("15"),
Minute: now.Format("04"),
HM: commitInfo.Time.Format("15:04"),
Hour: commitInfo.Time.Format("15"),
Minute: commitInfo.Time.Format("04"),
}

commitTemplateVarMap := map[string]interface{}{
Expand All @@ -89,63 +80,62 @@ func (f diffGen) buildMessage(stat *FileStat, ext string) (string, error) {
"Minute": commonVars.Minute,
}

if err := commitTempl.Execute(&commitMessage, commitTemplateVarMap); err != nil {
return "", err
var contentText bytes.Buffer
if err := commitTemplate.Execute(&contentText, commitTemplateVarMap); err != nil {
return "", fmt.Errorf("code content generate failed. Please check commit template in config. err: %w", err)
}

if tmpl, ok := f.conf.Templates[fileExt]; ok {
wrapperTempl, err := template.New("wrapper").Parse(tmpl)
codeTemplate, err := template.New("code").Parse(tmpl)
if err != nil {
return "", err
}

var buf bytes.Buffer
varMap := map[string]interface{}{
"Message": commitMessage.String(),
"Message": contentText.String(),
"HM": commonVars.HM,
"Hour": commonVars.Hour,
"Minute": commonVars.Minute,
}

if err := wrapperTempl.Execute(&buf, varMap); err != nil {
if err := codeTemplate.Execute(&buf, varMap); err != nil {
return "", err
}

return buf.String(), nil
}

return fmt.Sprintf(defaultCommitFormat, stat.Insert, stat.Delete), nil
return contentText.String(), nil
}

func (f diffGen) findExtensionAlias(ext string) string {
func (f diffGen) decideFileExtension(ext string) string {
if f.conf == nil {
return ext
}

searchExt := f.removeDot(ext)

for typ, aliases := range f.conf.Aliases {
for typ, aliases := range f.conf.Overwrites {
if typ != "default" {
for ext, alias := range aliases {
if ext == searchExt {
for fileType, alias := range aliases {
if ext == fileType {
return alias
}
}
}
}

if aliases, ok := f.conf.Aliases["default"]; ok {
for ext, alias := range aliases {
if ext == searchExt {
if aliases, ok := f.conf.Overwrites["default"]; ok {
for fileType, alias := range aliases {
if ext == fileType {
return alias
}
}
}

return searchExt
return ext
}

func (f diffGen) removeDot(ext string) string {
func (f diffGen) clearDot(ext string) string {
if strings.HasPrefix(ext, ".") {
return strings.Replace(ext, ".", "", 1)
}
Expand Down
82 changes: 82 additions & 0 deletions pkg/commit/diffgen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package commit

import (
"fmt"
"path/filepath"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"

"github.com/mesuutt/git-mirror/pkg/config"
)

func TestGenerateDiffWithDefaultsWhenConfigNotGiven(t *testing.T) {
// given
stat := FileStat{Insert: 1, Delete: 2, Ext: ".go"}

gen := NewDiffGenerator(nil)
// when
diff, err := gen.GenDiff([]FileStat{stat}, CommitInfo{Time: time.Now()})

// then
assert.Nil(t, err)
change := diff.Changes[0]
assert.Equal(t, "log.go", change.Filename)
assert.Equal(t, filepath.Join(strings.Split(time.Now().Format("2006-01-02"), "-")...), change.Dir)
assert.Equal(t, fmt.Sprintf(defaultLogMsgFormat, stat.Insert, stat.Delete), change.Text)
}

func TestGenerateDiffFilenameShouldNotChangedWhenNotHasDot(t *testing.T) {
// given
stat := FileStat{Insert: 1, Delete: 2, Ext: "Makefile"}

gen := NewDiffGenerator(nil)
// when
diff, err := gen.GenDiff([]FileStat{stat}, CommitInfo{Time: time.Now()})

// then
assert.Nil(t, err)
assert.Equal(t, "Makefile", diff.Changes[0].Filename)
}

func TestGenerateDiffWithCustomLogTemplate(t *testing.T) {
// given
stat := FileStat{Insert: 1, Delete: 2, Ext: ".go"}

gen := NewDiffGenerator(&config.Config{
Commit: config.CommitConfig{
Template: "insert: {{.InsertCount}}, delete: {{.DeleteCount}}, ext: {{.Ext}}, HM: {{.HM}}, Hour: {{.Hour}}, Minute: {{.Minute}}",
},
})

// when
commitTime := time.Now()
diff, err := gen.GenDiff([]FileStat{stat}, CommitInfo{Time: commitTime})

// then
assert.Nil(t, err)

assert.Equal(t, fmt.Sprintf("insert: %d, delete: %d, ext: %s, HM: %s, Hour: %s, Minute: %s", stat.Insert, stat.Delete, strings.ReplaceAll(stat.Ext, ".", ""), commitTime.Format("15:04"), commitTime.Format("15"), commitTime.Format("04")), diff.Changes[0].Text)
}

func TestGenerateDiffWithFileExtensionFromConfig(t *testing.T) {
// given
stat := FileStat{Insert: 1, Delete: 2, Ext: ".mod"}

gen := NewDiffGenerator(&config.Config{
Overwrites: map[string]map[string]string{
"default": {
"mod": "go",
},
},
})

// when
diff, err := gen.GenDiff([]FileStat{stat}, CommitInfo{Time: time.Now()})

// then
assert.Nil(t, err)
assert.Equal(t, "log.go", diff.Changes[0].Filename)
}
11 changes: 5 additions & 6 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
)

type Config struct {
Commit commitConfig
Aliases map[string]map[string]string
Templates map[string]string
Commit CommitConfig
Overwrites map[string]map[string]string
Templates map[string]string
}

type commitConfig struct {
type CommitConfig struct {
Template string
}

Expand All @@ -25,8 +25,7 @@ func ReadConfig(path string) (*Config, error) {

var conf Config
if err := toml.Unmarshal(bytes, &conf); err != nil {
fmt.Printf("config file parse failed: %s, error: %v\n", path, err)
return nil, err
return nil, fmt.Errorf("config file parse failed: %s, error: %w", path, err)
}

return &conf, nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/repo/fakerepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func NewFakeRepo() stdoutRepo {
return stdoutRepo{}
}

func (r stdoutRepo) AddStats(diff commit.Diff) error {
func (r stdoutRepo) AddStats(diff *commit.Diff) error {
for _, change := range diff.Changes {
filePath := path.Join(change.Dir, change.Filename)
fmt.Printf("%s\n\t%s\n", filePath, change.Text)
Expand Down
2 changes: 1 addition & 1 deletion pkg/repo/fsrepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func NewFsRepo(path string) fsRepo {
}

// AddStats writes diff stats to related files in mirror repo
func (r fsRepo) AddStats(diff commit.Diff) error {
func (r fsRepo) AddStats(diff *commit.Diff) error {
for i := range diff.Changes {
change := &diff.Changes[i]
absDirPath := filepath.Join(r.path, change.Dir)
Expand Down

0 comments on commit a2d7a2a

Please sign in to comment.