From f9567f0d4fc5cf6d0e1cea2d22289250c6b1cb2b Mon Sep 17 00:00:00 2001 From: Shulhan Date: Mon, 5 Jan 2026 21:47:09 +0700 Subject: lib/git: implement Equaler interface on Git The Equaler interface provide the method Equal that when implemented can be used to compare two instances of struct. --- lib/git/git.go | 23 ++++++++++++++++++++++ lib/git/git_example_test.go | 31 +++++++++++++++++++++++++++++ lib/git/git_test.go | 48 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/lib/git/git.go b/lib/git/git.go index 02877281..1fc5fde3 100644 --- a/lib/git/git.go +++ b/lib/git/git.go @@ -144,6 +144,24 @@ func Clone(remoteURL, dest string) (err error) { return nil } +// Equal return true if `v` is instance of `*Git` and has the same working +// directory. +// This implement [git.sr.ht/~shulhan/pakakeh.go/lib/reflect.Equaler] +// interface. +func (git *Git) Equal(v any) bool { + if v == nil { + return false + } + got, ok := v.(*Git) + if !ok { + return false + } + if got == nil { + return false + } + return git.String() == got.String() +} + // FetchAll will fetch the latest commits and tags from remote. func FetchAll(repoDir string) (err error) { cmd := exec.Command("git", "fetch") @@ -439,3 +457,8 @@ func RemoteBranches(repoDir string) ([]string, error) { return branches, nil } + +// String return the working directory with prefix "git+file://". +func (git *Git) String() string { + return `git+file://` + git.absDir +} diff --git a/lib/git/git_example_test.go b/lib/git/git_example_test.go index 0b55a251..968d4431 100644 --- a/lib/git/git_example_test.go +++ b/lib/git/git_example_test.go @@ -40,3 +40,34 @@ func ExampleGit_IsIgnored() { // "hello.go": false // "foo/hello.go": false } + +func ExampleGit_Equal() { + var agit *git.Git + var err error + agit, err = git.New(`testdata/Equal`) + if err != nil { + log.Fatal(err) + } + + var vgit *git.Git + var dir = `testdata/IsIgnored` + + vgit, err = git.New(dir) + if err != nil { + log.Fatal(err) + } + var got = agit.Equal(vgit) + fmt.Printf("On git %s: Equal is %t\n", dir, got) + + dir = `testdata/Equal` + vgit, err = git.New(dir) + if err != nil { + log.Fatal(err) + } + got = agit.Equal(vgit) + fmt.Printf("On git %s: Equal is %t\n", dir, got) + + // Output: + // On git testdata/IsIgnored: Equal is false + // On git testdata/Equal: Equal is true +} diff --git a/lib/git/git_test.go b/lib/git/git_test.go index 70a9ccca..65fe572d 100644 --- a/lib/git/git_test.go +++ b/lib/git/git_test.go @@ -134,6 +134,35 @@ Use '--' to separate paths from revisions, like this: } } +func TestGit_Equal(t *testing.T) { + type testCase struct { + v any + exp bool + } + var nilgit *Git + var listCase = []testCase{{ + v: nil, + }, { + v: os.ErrExist, + }, { + v: nilgit, + }} + + var agit *Git + var err error + agit, err = New(`testdata/Equal`) + if err != nil { + t.Fatal(err) + } + + var tc testCase + var got bool + for _, tc = range listCase { + got = agit.Equal(tc.v) + test.Assert(t, fmt.Sprintf(`%T`, tc.v), tc.exp, got) + } +} + func TestGetRemoteURL(t *testing.T) { cases := []struct { desc string @@ -393,3 +422,22 @@ func TestRemoteChange(t *testing.T) { test.Assert(t, "stdout", c.expStdout, mockStdout.String()) } } + +func TestGit_String(t *testing.T) { + var agit *Git + var err error + agit, err = New(`testdata/Equal`) + if err != nil { + t.Fatal(err) + } + + var wd string + wd, err = os.Getwd() + if err != nil { + t.Fatal(err) + } + + var exp = fmt.Sprintf(`git+file://%s/testdata/Equal`, wd) + var got = agit.String() + test.Assert(t, `String`, exp, got) +} -- cgit v1.3