shithub: furgit

ref: ab174c473618dd3743881cf44e02c2db4d1ecd5f
dir: /commitquery/queries_is_ancestor_integration_test.go/

View raw version
package commitquery_test

import (
	"errors"
	"testing"

	"codeberg.org/lindenii/furgit/commitquery"
	giterrors "codeberg.org/lindenii/furgit/errors"
	"codeberg.org/lindenii/furgit/internal/testgit"
	"codeberg.org/lindenii/furgit/object/fetch"
	objectid "codeberg.org/lindenii/furgit/object/id"
)

func TestIsMatchesGitMergeBase(t *testing.T) {
	t.Parallel()

	testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
		testRepo := testgit.NewRepo(t, testgit.RepoOptions{
			ObjectFormat: algo,
			Bare:         true,
			RefFormat:    "files",
		})

		_, tree1 := testRepo.MakeSingleFileTree(t, "one.txt", []byte("one\n"))
		c1 := testRepo.CommitTree(t, tree1, "c1")

		_, tree2 := testRepo.MakeSingleFileTree(t, "two.txt", []byte("two\n"))
		c2 := testRepo.CommitTree(t, tree2, "c2", c1)

		_, tree3 := testRepo.MakeSingleFileTree(t, "three.txt", []byte("three\n"))
		c3 := testRepo.CommitTree(t, tree3, "c3", c2)

		tag := testRepo.TagAnnotated(t, "tip", c2, "tip")

		store := testRepo.OpenObjectStore(t)

		got, err := commitquery.New(fetch.New(store), nil).IsAncestor(c1, tag)
		if err != nil {
			t.Fatalf("Is(c1, tag): %v", err)
		}

		want := gitMergeBaseIsAncestor(t, testRepo, c1, c2)
		if got != want {
			t.Fatalf("Is(c1, tag)=%v, want %v", got, want)
		}

		got, err = commitquery.New(fetch.New(store), nil).IsAncestor(c3, c2)
		if err != nil {
			t.Fatalf("Is(c3, c2): %v", err)
		}

		want = gitMergeBaseIsAncestor(t, testRepo, c3, c2)
		if got != want {
			t.Fatalf("Is(c3, c2)=%v, want %v", got, want)
		}
	})
}

func TestIsMatchesGitMergeBaseWithCommitGraph(t *testing.T) {
	t.Parallel()

	testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
		testRepo := testgit.NewRepo(t, testgit.RepoOptions{
			ObjectFormat: algo,
			Bare:         true,
			RefFormat:    "files",
		})

		_, tree1 := testRepo.MakeSingleFileTree(t, "one.txt", []byte("one\n"))
		c1 := testRepo.CommitTree(t, tree1, "c1")

		_, tree2 := testRepo.MakeSingleFileTree(t, "two.txt", []byte("two\n"))
		c2 := testRepo.CommitTree(t, tree2, "c2", c1)

		testRepo.UpdateRef(t, "refs/heads/main", c2)
		testRepo.SymbolicRef(t, "HEAD", "refs/heads/main")
		testRepo.CommitGraphWrite(t, "--reachable")

		store := testRepo.OpenObjectStore(t)
		graph := testRepo.OpenCommitGraph(t)

		got, err := commitquery.New(fetch.New(store), graph).IsAncestor(c1, c2)
		if err != nil {
			t.Fatalf("Is(c1, c2): %v", err)
		}

		want := gitMergeBaseIsAncestor(t, testRepo, c1, c2)
		if got != want {
			t.Fatalf("Is(c1, c2)=%v, want %v", got, want)
		}
	})
}

func TestIsMissingObject(t *testing.T) {
	t.Parallel()

	testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
		testRepo := testgit.NewRepo(t, testgit.RepoOptions{
			ObjectFormat: algo,
			Bare:         true,
			RefFormat:    "files",
		})

		_, treeID, commitID := testRepo.MakeCommit(t, "missing")

		testRepo.RemoveLooseObject(t, treeID)

		store := testRepo.OpenObjectStore(t)

		_, err := commitquery.New(fetch.New(store), nil).IsAncestor(treeID, commitID)
		if err == nil {
			t.Fatal("expected error")
		}

		missing, ok := errors.AsType[*giterrors.ObjectMissingError](err)
		if !ok {
			t.Fatalf("expected ObjectMissingError, got %T (%v)", err, err)
		}

		if missing.OID != treeID {
			t.Fatalf("missing oid = %s, want %s", missing.OID, treeID)
		}
	})
}

// gitMergeBaseIsAncestor reports Git's merge-base ancestry answer.
func gitMergeBaseIsAncestor(t *testing.T, testRepo *testgit.TestRepo, left, right objectid.ObjectID) bool {
	t.Helper()

	out := testRepo.Run(t, "merge-base", left.String(), right.String())

	return out == left.String()
}