diff options
| author | Shulhan <ms@kilabit.info> | 2026-01-13 21:06:31 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2026-01-13 21:06:31 +0700 |
| commit | 06eb22e30f855d70468640ea72e23c43e384c793 (patch) | |
| tree | ff7b5a89b591b6eee0ab2e50b7960060c1c50086 | |
| parent | cdfebe3f55dc53872079a96a9a5dd6970bc2980e (diff) | |
| download | pakakeh.go-06eb22e30f855d70468640ea72e23c43e384c793.tar.xz | |
lib/git: add method LogFollow
The LogFollow method return history of single file `path`, following
rename.
This method accept second paramter "format", default to
'%h,%at,%an,%ae,%s' which print short hash, author commit timestamp,
author name, author email, and subject; respectively separated by comma.
| -rw-r--r-- | CHANGELOG.adoc | 9 | ||||
| -rw-r--r-- | lib/git/git.go | 33 | ||||
| -rw-r--r-- | lib/git/git_test.go | 24 |
3 files changed, 66 insertions, 0 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 5d9c003d..2d640a1a 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -46,6 +46,15 @@ to the request, and the server will return immediately. Zero status code indicates that the function did not process the request, it is up to server to process the returned node `out`. +**🌱 lib/git: add method LogFollow** + +The LogFollow method return history of single file `path`, following +rename. + +This method accept second paramter "format", default to +'%h,%at,%an,%ae,%s' which print short hash, author commit timestamp, +author name, author email, and subject; respectively separated by comma. + //}}} //{{{ [#v0_60_2] diff --git a/lib/git/git.go b/lib/git/git.go index 43a27bf5..3ee5c376 100644 --- a/lib/git/git.go +++ b/lib/git/git.go @@ -272,6 +272,39 @@ func (git *Git) IsIgnored(path string) (b bool) { return false } +// LogFollow return history of single file `path`, following rename. +// +// The format parameter set the output format, default to '%h,%at,%an,%ae,%s' +// which print short hash, author commit timestamp, author name, author email, +// and subject; respectively separated by comma. +func (git *Git) LogFollow(path, format string) (logs []string, err error) { + if format == `` { + format = `%h,%at,%an,%ae,%s` + } + + var cmd *exec.Cmd + cmd = exec.Command(`git`) + cmd.Args = append(cmd.Args, `--no-pager`, `log`, `--follow`, `--format=`+format, path) + cmd.Dir = git.absDir + cmd.Stderr = _stderr + + var stdout []byte + stdout, err = cmd.Output() + if err != nil { + return nil, fmt.Errorf(`LogFollow %s: %w`, path, err) + } + + lines := bytes.Split(stdout, []byte{'\n'}) + logs = make([]string, 0, len(lines)) + for _, line := range lines { + if len(line) == 0 { + break + } + logs = append(logs, string(line)) + } + return logs, nil +} + // LatestCommit get the latest commit hash in short format from "ref". // If ref is empty, its default to "origin/master". func LatestCommit(repoDir, ref string) (commit string, err error) { diff --git a/lib/git/git_test.go b/lib/git/git_test.go index 2ea5aba4..e4cb5a26 100644 --- a/lib/git/git_test.go +++ b/lib/git/git_test.go @@ -194,6 +194,30 @@ func TestGit_IsIgnored(t *testing.T) { } } +func TestGit_LogFollow(t *testing.T) { + agit, err := New(`../../`) + if err != nil { + t.Fatal(err) + } + path := `lib/_hunspell/affix.go` + logs, err := agit.LogFollow(path, ``) + if err != nil { + t.Fatal(err) + } + exp := []string{ + `144549f8,1737804887,Shulhan,ms@kilabit.info,lib/hunspell: rename the package to "_hunspell"`, + `66e6542e,1694357806,Shulhan,ms@kilabit.info,lib/hunspell: realign struct for better size allocation`, + `0c9abc1a,1652108042,Shulhan,ms@kilabit.info,all: reformat all codes using gofmt 1.19 (the Go tip)`, + `9ca9757d,1591803682,Shulhan,m.shulhan@gmail.com,all: update email address`, + `b0fa5a47,1585156612,Shulhan,m.shulhan@gmail.com,all: fix and suppress linter warnings`, + `33d58b98,1585151378,Shulhan,m.shulhan@gmail.com,hunspell: add field Parent to Stem`, + `367e15a8,1585139124,Shulhan,m.shulhan@gmail.com,hunspell: change the stem.apply parameter from string to *Stem`, + `099a24de,1579628651,Shulhan,m.shulhan@gmail.com,hunspell: split the affix options and dictionary into different types`, + `3d772dff,1572967023,Shulhan,m.shulhan@gmail.com,lib/hunspell: implementation of hunspell in pure Go`, + } + test.Assert(t, path, exp, logs) +} + func TestGetRemoteURL(t *testing.T) { cases := []struct { desc string |
