changelog generator & diff tool
stormlightlabs.github.io/git-storm/
changelog
changeset
markdown
golang
git
1package testutils
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7 "time"
8
9 "github.com/go-git/go-git/v6"
10 "github.com/go-git/go-git/v6/plumbing"
11 "github.com/go-git/go-git/v6/plumbing/object"
12)
13
14// SetupTestRepo creates a git repository in a temporary directory with sample
15// commits. The repository contains multiple commits with different types of
16// changes to support testing diff algorithms, changelog generation, and git log
17// parsing.
18func SetupTestRepo(t *testing.T) *git.Repository {
19 t.Helper()
20 dir := t.TempDir()
21
22 repo, err := git.PlainInit(dir, false)
23 if err != nil {
24 t.Fatalf("failed to init repo: %v", err)
25 }
26
27 w, err := repo.Worktree()
28 if err != nil {
29 t.Fatalf("failed to get worktree: %v", err)
30 }
31
32 commits := []struct {
33 name, content, message string
34 }{
35 {"README.md", "# Project\n\nInitial version", "chore: initial commit"},
36 {"a.txt", "hello world", "feat: add hello world"},
37 {"b.txt", "fixed bug", "fix: patch file"},
38 {"a.txt", "hello world\ngoodbye world", "feat: add goodbye"},
39 {"c.txt", "new feature\nwith multiple lines\nof content", "feat: add multi-line file"},
40 {"b.txt", "fixed bug\nwith proper handling", "fix: improve error handling"},
41 }
42
43 for _, c := range commits {
44 path := filepath.Join(dir, c.name)
45 if err := os.WriteFile(path, []byte(c.content), 0644); err != nil {
46 t.Fatalf("failed to write file %s: %v", c.name, err)
47 }
48 if _, err := w.Add(c.name); err != nil {
49 t.Fatalf("failed to add file %s: %v", c.name, err)
50 }
51 if _, err := w.Commit(c.message, &git.CommitOptions{
52 Author: &object.Signature{
53 Name: "Test Author",
54 Email: "test@example.com",
55 When: time.Now(),
56 },
57 }); err != nil {
58 t.Fatalf("commit failed: %v", err)
59 }
60 }
61 return repo
62}
63
64// CreateTag creates a lightweight tag at the current HEAD of the repository.
65func CreateTag(t *testing.T, repo *git.Repository, tagName string) {
66 t.Helper()
67 head, err := repo.Head()
68 if err != nil {
69 t.Fatalf("failed to get HEAD: %v", err)
70 }
71
72 _, err = repo.CreateTag(tagName, head.Hash(), nil)
73 if err != nil {
74 t.Fatalf("failed to create tag %s: %v", tagName, err)
75 }
76}
77
78// CreateTagAtCommit creates a lightweight tag at a specific commit hash.
79func CreateTagAtCommit(t *testing.T, repo *git.Repository, tagName, commitHash string) error {
80 t.Helper()
81 hash, err := repo.ResolveRevision(plumbing.Revision(commitHash))
82 if err != nil {
83 return err
84 }
85
86 _, err = repo.CreateTag(tagName, *hash, nil)
87 return err
88}
89
90// GetCommitHistory returns all commits in the repository from HEAD backwards.
91func GetCommitHistory(t *testing.T, repo *git.Repository) []*object.Commit {
92 t.Helper()
93 head, err := repo.Head()
94 if err != nil {
95 t.Fatalf("failed to get HEAD: %v", err)
96 }
97
98 commitIter, err := repo.Log(&git.LogOptions{From: head.Hash()})
99 if err != nil {
100 t.Fatalf("failed to get commit log: %v", err)
101 }
102
103 var commits []*object.Commit
104 err = commitIter.ForEach(func(c *object.Commit) error {
105 commits = append(commits, c)
106 return nil
107 })
108 if err != nil {
109 t.Fatalf("failed to iterate commits: %v", err)
110 }
111
112 return commits
113}
114
115// AddCommit adds a new commit to the repository with the given file changes.
116func AddCommit(t *testing.T, repo *git.Repository, filename, content, message string) {
117 t.Helper()
118 w, err := repo.Worktree()
119 if err != nil {
120 t.Fatalf("failed to get worktree: %v", err)
121 }
122
123 path := filepath.Join(w.Filesystem.Root(), filename)
124 if err := os.WriteFile(path, []byte(content), 0644); err != nil {
125 t.Fatalf("failed to write file %s: %v", filename, err)
126 }
127
128 if _, err := w.Add(filename); err != nil {
129 t.Fatalf("failed to add file %s: %v", filename, err)
130 }
131
132 if _, err := w.Commit(message, &git.CommitOptions{
133 Author: &object.Signature{
134 Name: "Test Author",
135 Email: "test@example.com",
136 When: time.Now(),
137 },
138 }); err != nil {
139 t.Fatalf("commit failed: %v", err)
140 }
141}