blob: 08c9800d6b72ecd70b5706ff22cf56f161812087 [file] [log] [blame] [edit]
package git
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
exec_testutils "go.skia.org/infra/go/exec/testutils"
"go.skia.org/infra/go/testutils"
)
func TestGitDetails(t *testing.T) {
start := time.Now().Add(-2 * time.Second) // Need a small buffer due to 1-second granularity.
ctx, gb, commits := setup(t)
defer gb.Cleanup()
g := CheckoutDir(gb.Dir())
for i, c := range commits {
d, err := g.Details(ctx, c)
require.NoError(t, err)
require.Equal(t, c, d.Hash)
require.True(t, strings.Contains(d.Author, "@"))
num := len(commits) - 1 - i
require.Equal(t, fmt.Sprintf("Commit Title #%d", num), d.Subject)
if num != 0 {
require.Equal(t, 1, len(d.Parents))
} else {
require.Equal(t, 0, len(d.Parents))
}
require.Equal(t, fmt.Sprintf("Commit Body #%d", num), d.Body)
require.True(t, d.Timestamp.After(start))
}
}
func TestGitBranch(t *testing.T) {
ctx, gb, commits := setup(t)
defer gb.Cleanup()
tmpDir, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer testutils.RemoveAll(t, tmpDir)
g, err := NewCheckout(ctx, gb.Dir(), tmpDir)
require.NoError(t, err)
branches, err := g.Branches(ctx)
require.NoError(t, err)
require.Equal(t, 1, len(branches))
main := branches[0]
require.Equal(t, commits[0], main.Head)
require.Equal(t, MainBranch, main.Name)
// Add a branch.
gb.CreateBranchTrackBranch(ctx, "newbranch", MainBranch)
c10 := gb.CommitGen(ctx, "branchfile")
_, err = g.Git(ctx, "fetch", DefaultRemote)
require.NoError(t, err)
_, err = g.Git(ctx, "checkout", "-b", "newbranch", "-t", "origin/newbranch")
require.NoError(t, err)
branches, err = g.Branches(ctx)
require.NoError(t, err)
require.Equal(t, 2, len(branches))
m, o := branches[0], branches[1]
if o.Name == MainBranch {
m, o = branches[1], branches[0]
}
require.Equal(t, commits[0], m.Head)
require.Equal(t, MainBranch, m.Name)
require.Equal(t, c10, o.Head)
require.Equal(t, "newbranch", o.Name)
// Add an ambiguous ref to ensure that Branches() doesn't have a
// problem with it.
git, err := Executable(ctx)
require.NoError(t, err)
exec_testutils.Run(t, ctx, gb.Dir(), git, "update-ref", "refs/heads/meta/config", commits[6])
exec_testutils.Run(t, ctx, gb.Dir(), git, "push", DefaultRemote, "refs/heads/meta/config")
exec_testutils.Run(t, ctx, gb.Dir(), git, "update-ref", "refs/tags/meta/config", commits[3])
exec_testutils.Run(t, ctx, gb.Dir(), git, "push", DefaultRemote, "refs/tags/meta/config")
_, err = g.Git(ctx, "fetch")
require.NoError(t, err)
_, err = g.Git(ctx, "checkout", "-b", "meta/config", "-t", "origin/meta/config")
require.NoError(t, err)
// Verify that it's actually ambiguous. We're also testing that RevParse
// returns an error for ambiguous refs, since Git doesn't exit with non-
// zero code in that case.
_, err = g.RevParse(ctx, "meta/config")
require.Error(t, err)
// Make sure Branches() succeeds and uses the correct ref.
branches, err = g.Branches(ctx)
require.NoError(t, err)
checked := false
for _, b := range branches {
if b.Name == "meta/config" {
require.Equal(t, b.Head, commits[6])
checked = true
break
}
}
require.True(t, checked)
}
func TestIsAncestor(t *testing.T) {
ctx, gb, commits := setup(t)
defer gb.Cleanup()
tmpDir, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer testutils.RemoveAll(t, tmpDir)
g, err := NewCheckout(ctx, gb.Dir(), tmpDir)
require.NoError(t, err)
// Commits are in decreasing chronological order; commits[0] is the most
// recent and therefore is not an ancestor of commits[9].
b, err := g.IsAncestor(ctx, commits[0], commits[len(commits)-1])
require.NoError(t, err)
require.False(t, b)
for i := 0; i < len(commits)-1; i++ {
b, err := g.IsAncestor(ctx, commits[i], commits[i+1])
require.NoError(t, err)
require.False(t, b)
b, err = g.IsAncestor(ctx, commits[i+1], commits[i])
require.NoError(t, err)
require.True(t, b)
}
}
func TestGetFile(t *testing.T) {
ctx, gb, commits := setup(t)
defer gb.Cleanup()
tmpDir, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer testutils.RemoveAll(t, tmpDir)
g, err := NewCheckout(ctx, gb.Dir(), tmpDir)
require.NoError(t, err)
contents, err := g.GetFile(ctx, checkedInFile, "HEAD")
require.NoError(t, err)
contentsAtHead, err := os.ReadFile(filepath.Join(g.Dir(), checkedInFile))
require.NoError(t, err)
require.Equal(t, string(contentsAtHead), contents)
contents, err = g.GetFile(ctx, checkedInFile, commits[1])
require.NoError(t, err)
// We use rng to change file content between commits so it should be
// different.
require.NotEqual(t, string(contentsAtHead), contents)
}
func TestReadUpdateSubmodule(t *testing.T) {
ctx, gb, _ := setup(t)
defer gb.Cleanup()
tmpDir, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer testutils.RemoveAll(t, tmpDir)
g, err := NewCheckout(ctx, gb.Dir(), tmpDir)
require.NoError(t, err)
// Create submodule
require.NoError(t, err)
_, err = g.Git(ctx, "-c", "protocol.file.allow=always", "submodule", "add", g.Dir(), "my-submodule")
require.NoError(t, err)
hash, err := g.FullHash(ctx, "HEAD")
require.NoError(t, err)
_, err = g.Git(ctx, "commit", "-m", "update submodule")
require.NoError(t, err)
// Test Read submodule
contents, err := g.ReadSubmodule(ctx, "my-submodule", "HEAD")
require.NoError(t, err)
require.Equal(t, hash, contents)
// Test Read directory
contents, err = g.ReadSubmodule(ctx, ".", "HEAD")
require.Error(t, err)
require.Equal(t, "", contents)
// Test Write & Read
newHash := "2222222222222222222222222222222222222222"
err = g.UpdateSubmodule(ctx, "my-submodule", newHash)
require.NoError(t, err)
_, err = g.Git(ctx, "commit", "-m", "update submodule #2")
require.NoError(t, err)
contents, err = g.ReadSubmodule(ctx, "my-submodule", "HEAD")
require.NoError(t, err)
require.Equal(t, newHash, contents)
}