26f897c1ec
release / release-please (push) Failing after 1m49s
docs / build (push) Failing after 6m34s
release / build-and-upload (arm64, linux) (push) Has been cancelled
release / build-and-upload (arm64, windows) (push) Has been cancelled
release / build-darwin (amd64, darwin) (push) Has been cancelled
release / checksums (push) Has been cancelled
release / finalize (push) Has been cancelled
release / build-darwin (arm64, darwin) (push) Has been cancelled
release / build-and-upload (amd64, linux) (push) Has been cancelled
release / build-and-upload (amd64, windows) (push) Has been cancelled
docs / deploy (push) Has been cancelled
226 lines
5.7 KiB
Go
226 lines
5.7 KiB
Go
package git
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestDiff(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
|
|
// get initial commit SHA
|
|
base := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
// make a change and commit
|
|
writeFile(t, filepath.Join(dir, "file.txt"), "hello\n")
|
|
run(t, dir, "git", "add", ".")
|
|
run(t, dir, "git", "commit", "-m", "add file")
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
diff, err := Diff(ctx, dir, base, head)
|
|
if err != nil {
|
|
t.Fatalf("Diff failed: %v", err)
|
|
}
|
|
if !strings.Contains(diff, "file.txt") {
|
|
t.Fatalf("diff should mention file.txt, got: %q", diff)
|
|
}
|
|
if !strings.Contains(diff, "+hello") {
|
|
t.Fatalf("diff should contain +hello, got: %q", diff)
|
|
}
|
|
}
|
|
|
|
func TestDiffNameOnly(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
|
|
base := run(t, dir, "git", "rev-parse", "HEAD")
|
|
writeFile(t, filepath.Join(dir, "a.txt"), "a\n")
|
|
writeFile(t, filepath.Join(dir, "b.txt"), "b\n")
|
|
run(t, dir, "git", "add", ".")
|
|
run(t, dir, "git", "commit", "-m", "add files")
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
files, err := DiffNameOnly(ctx, dir, base, head)
|
|
if err != nil {
|
|
t.Fatalf("DiffNameOnly: %v", err)
|
|
}
|
|
if len(files) != 2 {
|
|
t.Fatalf("got %d files, want 2: %v", len(files), files)
|
|
}
|
|
want := map[string]bool{"a.txt": true, "b.txt": true}
|
|
for _, f := range files {
|
|
if !want[f] {
|
|
t.Errorf("unexpected file %q", f)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCommitTime(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
ts, err := CommitTime(ctx, dir, head)
|
|
if err != nil {
|
|
t.Fatalf("CommitTime: %v", err)
|
|
}
|
|
if ts.IsZero() {
|
|
t.Error("expected non-zero commit time")
|
|
}
|
|
}
|
|
|
|
func TestCommitAuthorEmail(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
email, err := CommitAuthorEmail(ctx, dir, head)
|
|
if err != nil {
|
|
t.Fatalf("CommitAuthorEmail: %v", err)
|
|
}
|
|
if email == "" {
|
|
t.Error("expected non-empty author email")
|
|
}
|
|
}
|
|
|
|
func TestDiffEmpty(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
diff, err := Diff(ctx, dir, head, head)
|
|
if err != nil {
|
|
t.Fatalf("Diff failed: %v", err)
|
|
}
|
|
if diff != "" {
|
|
t.Fatalf("expected empty diff, got: %q", diff)
|
|
}
|
|
}
|
|
|
|
func TestDiffAgainstEmptyTree(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
const emptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
|
|
|
diff, err := Diff(ctx, dir, emptyTreeSHA, head)
|
|
if err != nil {
|
|
t.Fatalf("Diff against empty tree failed: %v", err)
|
|
}
|
|
if !strings.Contains(diff, "README.md") {
|
|
t.Fatalf("diff should mention README.md, got: %q", diff)
|
|
}
|
|
if !strings.Contains(diff, "+# test") {
|
|
t.Fatalf("diff should include initial file contents, got: %q", diff)
|
|
}
|
|
}
|
|
|
|
func TestDiffHead(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
|
|
// No changes — should be empty
|
|
diff, err := DiffHead(ctx, dir)
|
|
if err != nil {
|
|
t.Fatalf("DiffHead (clean) failed: %v", err)
|
|
}
|
|
if diff != "" {
|
|
t.Fatalf("expected empty diff for clean tree, got: %q", diff)
|
|
}
|
|
|
|
// Unstaged changes
|
|
writeFile(t, filepath.Join(dir, "new.txt"), "content\n")
|
|
run(t, dir, "git", "add", "new.txt")
|
|
writeFile(t, filepath.Join(dir, "new.txt"), "modified\n")
|
|
|
|
diff, err = DiffHead(ctx, dir)
|
|
if err != nil {
|
|
t.Fatalf("DiffHead (unstaged) failed: %v", err)
|
|
}
|
|
if !strings.Contains(diff, "new.txt") {
|
|
t.Fatalf("diff should mention new.txt, got: %q", diff)
|
|
}
|
|
if !strings.Contains(diff, "+modified") {
|
|
t.Fatalf("diff should contain +modified, got: %q", diff)
|
|
}
|
|
}
|
|
|
|
func TestDiffHead_StagedChanges(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
|
|
// Staged but uncommitted changes
|
|
writeFile(t, filepath.Join(dir, "staged.txt"), "staged content\n")
|
|
run(t, dir, "git", "add", "staged.txt")
|
|
|
|
diff, err := DiffHead(ctx, dir)
|
|
if err != nil {
|
|
t.Fatalf("DiffHead (staged) failed: %v", err)
|
|
}
|
|
if !strings.Contains(diff, "staged.txt") {
|
|
t.Fatalf("diff should mention staged.txt, got: %q", diff)
|
|
}
|
|
if !strings.Contains(diff, "+staged content") {
|
|
t.Fatalf("diff should contain +staged content, got: %q", diff)
|
|
}
|
|
}
|
|
|
|
func TestLog(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
|
|
base := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
writeFile(t, filepath.Join(dir, "a.txt"), "a\n")
|
|
run(t, dir, "git", "add", ".")
|
|
run(t, dir, "git", "commit", "-m", "first change")
|
|
|
|
writeFile(t, filepath.Join(dir, "b.txt"), "b\n")
|
|
run(t, dir, "git", "add", ".")
|
|
run(t, dir, "git", "commit", "-m", "second change")
|
|
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
|
|
log, err := Log(ctx, dir, base, head)
|
|
if err != nil {
|
|
t.Fatalf("Log failed: %v", err)
|
|
}
|
|
if !strings.Contains(log, "first change") {
|
|
t.Fatalf("log should contain first change, got: %q", log)
|
|
}
|
|
if !strings.Contains(log, "second change") {
|
|
t.Fatalf("log should contain second change, got: %q", log)
|
|
}
|
|
}
|
|
|
|
func TestLogAgainstEmptyTree(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
head := run(t, dir, "git", "rev-parse", "HEAD")
|
|
const emptyTreeSHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
|
|
|
log, err := Log(ctx, dir, emptyTreeSHA, head)
|
|
if err != nil {
|
|
t.Fatalf("Log against empty tree failed: %v", err)
|
|
}
|
|
if !strings.Contains(log, "initial") {
|
|
t.Fatalf("log should contain initial commit, got: %q", log)
|
|
}
|
|
}
|
|
|
|
func TestHeadSHA(t *testing.T) {
|
|
dir := initTestRepo(t)
|
|
ctx := context.Background()
|
|
|
|
sha, err := HeadSHA(ctx, dir)
|
|
if err != nil {
|
|
t.Fatalf("HeadSHA failed: %v", err)
|
|
}
|
|
if len(sha) != 40 {
|
|
t.Fatalf("expected 40-char SHA, got %d chars: %q", len(sha), sha)
|
|
}
|
|
}
|