aboutsummaryrefslogtreecommitdiff
path: root/cmd/kdev/record_extractor.go
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2024-10-04 10:25:53 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2024-10-04 10:35:35 +0200
commitd174bb92ed033ac4235c5e7b30bf617575779fb9 (patch)
tree9a8e8551284b3b3c3230a37c7003dd9b0deb811e /cmd/kdev/record_extractor.go
parent48aba2f0c40662186ff5d49dcca44ce563b365fd (diff)
refactor(kdev): Support several record extractorsv0.5.1
Diffstat (limited to 'cmd/kdev/record_extractor.go')
-rw-r--r--cmd/kdev/record_extractor.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/cmd/kdev/record_extractor.go b/cmd/kdev/record_extractor.go
new file mode 100644
index 0000000..2dc079e
--- /dev/null
+++ b/cmd/kdev/record_extractor.go
@@ -0,0 +1,95 @@
+package main
+
+import (
+ "fmt"
+ "io/fs"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing/object"
+ "github.com/martinlehoux/kagamigo/kcore"
+)
+
+type RecordExtractor interface {
+ Extract(keyword string, path string, line int) Record
+}
+
+type StatRecordExtractor struct {
+ fileInfo fs.FileInfo
+}
+
+func NewStatRecordExtractor(absolutePath string) *StatRecordExtractor {
+ fileInfo, err := os.Stat(absolutePath)
+ kcore.Expect(err, "Error getting file info")
+
+ return &StatRecordExtractor{
+ fileInfo: fileInfo,
+ }
+}
+
+func (re *StatRecordExtractor) Extract(keyword string, path string, line int) Record {
+ return Record{
+ keyword: keyword,
+ path: path,
+ line: line,
+ date: re.fileInfo.ModTime(),
+ }
+}
+
+type GoGitRecordExtractor struct {
+ blame *git.BlameResult
+}
+
+func NewGoGitRecordExtractor(head *object.Commit, path string) *GoGitRecordExtractor {
+ blame, err := git.Blame(head, path)
+ if err == object.ErrFileNotFound {
+ return nil
+ }
+ return &GoGitRecordExtractor{
+ blame: blame,
+ }
+}
+
+func (re *GoGitRecordExtractor) Extract(keyword string, path string, line int) Record {
+ return Record{
+ keyword: keyword,
+ path: path,
+ line: line,
+ date: re.blame.Lines[line-1].Date,
+ }
+}
+
+type GitRecordExtractor struct {
+ repoPath string
+}
+
+func (re *GitRecordExtractor) Extract(keyword string, path string, line int) Record {
+ record := Record{
+ keyword: keyword,
+ path: path,
+ line: line,
+ }
+ gitArgs := []string{"blame", "-L", fmt.Sprintf("%d,%d", line, line), "--porcelain", path}
+ cmd := exec.Command("git", gitArgs...) // #nosec G204
+ cmd.Dir = re.repoPath
+ output, err := cmd.Output()
+
+ if err != nil {
+ panic(kcore.Wrap(err, fmt.Sprintf("Error running: git %s", strings.Join(gitArgs, " "))))
+ }
+
+ for _, blameLine := range strings.Split(string(output), "\n") {
+ if strings.HasPrefix(blameLine, "author-time ") {
+ timestamp, err := strconv.ParseInt(strings.TrimPrefix(blameLine, "author-time "), 10, 64)
+ kcore.Expect(err, "Error parsing timestamp")
+ record.date = time.Unix(timestamp, 0)
+ return record
+ }
+ }
+ kcore.Assert(false, "No date found in git blame output")
+ return Record{}
+}