talas-group/talas-wiki/internal/wiki/git.go
senke 66471934af Initial commit: Talas Group project management & documentation
Knowledge base of ~80+ markdown files across 14 domains (00-13),
Logseq graph, hardware design files (KiCAD), infrastructure configs,
and talas-wiki static site.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 20:10:41 +02:00

153 lines
3.4 KiB
Go

package wiki
import (
"fmt"
"os/exec"
"strings"
"time"
)
type GitCommit struct {
Hash string
Author string
Date time.Time
Message string
}
type GitDiff struct {
Hash string
Message string
Diff string
}
// GitAutoCommit stages and commits a file change
func (idx *Index) GitAutoCommit(relPath string, message string) error {
// Check if we're in a git repo
cmd := exec.Command("git", "rev-parse", "--git-dir")
cmd.Dir = idx.docsRoot
if err := cmd.Run(); err != nil {
return nil // Not a git repo, silently skip
}
// Stage the file
cmd = exec.Command("git", "add", relPath+".md")
cmd.Dir = idx.docsRoot
if err := cmd.Run(); err != nil {
return fmt.Errorf("git add failed: %w", err)
}
// Commit
if message == "" {
message = fmt.Sprintf("wiki: update %s", relPath)
}
cmd = exec.Command("git", "commit", "-m", message)
cmd.Dir = idx.docsRoot
if err := cmd.Run(); err != nil {
// Might fail if nothing to commit, that's ok
return nil
}
return nil
}
// GitHistory returns the commit history for a specific file
func (idx *Index) GitHistory(urlPath string, maxEntries int) ([]GitCommit, error) {
cmd := exec.Command("git", "rev-parse", "--git-dir")
cmd.Dir = idx.docsRoot
if err := cmd.Run(); err != nil {
return nil, nil // Not a git repo
}
filePath := urlPath + ".md"
cmd = exec.Command("git", "log",
fmt.Sprintf("-n%d", maxEntries),
"--format=%H|%an|%aI|%s",
"--", filePath)
cmd.Dir = idx.docsRoot
output, err := cmd.Output()
if err != nil {
return nil, nil
}
var commits []GitCommit
for _, line := range strings.Split(strings.TrimSpace(string(output)), "\n") {
if line == "" {
continue
}
parts := strings.SplitN(line, "|", 4)
if len(parts) < 4 {
continue
}
date, _ := time.Parse(time.RFC3339, parts[2])
commits = append(commits, GitCommit{
Hash: parts[0],
Author: parts[1],
Date: date,
Message: parts[3],
})
}
return commits, nil
}
// GitDiffForCommit returns the diff for a specific commit and file
func (idx *Index) GitDiffForCommit(urlPath string, hash string) (*GitDiff, error) {
filePath := urlPath + ".md"
// Get commit message
cmd := exec.Command("git", "log", "-1", "--format=%s", hash)
cmd.Dir = idx.docsRoot
msgOut, err := cmd.Output()
if err != nil {
return nil, err
}
// Get diff
cmd = exec.Command("git", "diff", hash+"~1", hash, "--", filePath)
cmd.Dir = idx.docsRoot
diffOut, _ := cmd.Output()
return &GitDiff{
Hash: hash,
Message: strings.TrimSpace(string(msgOut)),
Diff: string(diffOut),
}, nil
}
// GitRecentActivity returns the most recent commits across all files
func (idx *Index) GitRecentActivity(maxEntries int) ([]GitCommit, error) {
cmd := exec.Command("git", "rev-parse", "--git-dir")
cmd.Dir = idx.docsRoot
if err := cmd.Run(); err != nil {
return nil, nil
}
cmd = exec.Command("git", "log",
fmt.Sprintf("-n%d", maxEntries),
"--format=%H|%an|%aI|%s",
"--diff-filter=AMRD",
"--", "*.md")
cmd.Dir = idx.docsRoot
output, err := cmd.Output()
if err != nil {
return nil, nil
}
var commits []GitCommit
for _, line := range strings.Split(strings.TrimSpace(string(output)), "\n") {
if line == "" {
continue
}
parts := strings.SplitN(line, "|", 4)
if len(parts) < 4 {
continue
}
date, _ := time.Parse(time.RFC3339, parts[2])
commits = append(commits, GitCommit{
Hash: parts[0],
Author: parts[1],
Date: date,
Message: parts[3],
})
}
return commits, nil
}