package git
import (
"os"
"testing"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-billy/v5/util"
fixtures "github.com/go-git/go-git-fixtures/v4"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) { TestingT(t) }
type BaseSuite struct {
fixtures.Suite
Repository *Repository
cache map[string]*Repository
}
func (s *BaseSuite) SetUpSuite(c *C) {
s.buildBasicRepository(c)
s.cache = make(map[string]*Repository)
}
func (s *BaseSuite) TearDownSuite(c *C) {
s.Suite.TearDownSuite(c)
}
func (s *BaseSuite) buildBasicRepository(_ *C) {
f := fixtures.Basic().One()
s.Repository = s.NewRepository(f)
}
// NewRepository returns a new repository using the .git folder, if the fixture
// is tagged as worktree the filesystem from fixture is used, otherwise a new
// memfs filesystem is used as worktree.
func (s *BaseSuite) NewRepository(f *fixtures.Fixture) *Repository {
var worktree, dotgit billy.Filesystem
if f.Is("worktree") {
r, err := PlainOpen(f.Worktree().Root())
if err != nil {
panic(err)
}
return r
}
dotgit = f.DotGit()
worktree = memfs.New()
st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault())
r, err := Open(st, worktree)
if err != nil {
panic(err)
}
return r
}
// NewRepositoryWithEmptyWorktree returns a new repository using the .git folder
// from the fixture but without a empty memfs worktree, the index and the
// modules are deleted from the .git folder.
func (s *BaseSuite) NewRepositoryWithEmptyWorktree(f *fixtures.Fixture) *Repository {
dotgit := f.DotGit()
err := dotgit.Remove("index")
if err != nil {
panic(err)
}
err = util.RemoveAll(dotgit, "modules")
if err != nil {
panic(err)
}
worktree := memfs.New()
st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault())
r, err := Open(st, worktree)
if err != nil {
panic(err)
}
return r
}
func (s *BaseSuite) NewRepositoryFromPackfile(f *fixtures.Fixture) *Repository {
h := f.PackfileHash
if r, ok := s.cache[h]; ok {
return r
}
storer := memory.NewStorage()
p := f.Packfile()
defer func() { _ = p.Close() }()
if err := packfile.UpdateObjectStorage(storer, p); err != nil {
panic(err)
}
err := storer.SetReference(plumbing.NewHashReference(plumbing.HEAD, plumbing.NewHash(f.Head)))
if err != nil {
panic(err)
}
r, err := Open(storer, memfs.New())
if err != nil {
panic(err)
}
s.cache[h] = r
return r
}
func (s *BaseSuite) GetBasicLocalRepositoryURL() string {
fixture := fixtures.Basic().One()
return s.GetLocalRepositoryURL(fixture)
}
func (s *BaseSuite) GetLocalRepositoryURL(f *fixtures.Fixture) string {
return f.DotGit().Root()
}
func (s *BaseSuite) TemporalDir() (path string, clean func()) {
fs := osfs.New(os.TempDir())
relPath, err := util.TempDir(fs, "", "")
if err != nil {
panic(err)
}
path = fs.Join(fs.Root(), relPath)
clean = func() {
_ = util.RemoveAll(fs, relPath)
}
return
}
func (s *BaseSuite) TemporalHomeDir() (path string, clean func()) {
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
fs := osfs.New(home)
relPath, err := util.TempDir(fs, "", "")
if err != nil {
panic(err)
}
path = fs.Join(fs.Root(), relPath)
clean = func() {
_ = util.RemoveAll(fs, relPath)
}
return
}
func (s *BaseSuite) TemporalFilesystem() (fs billy.Filesystem, clean func()) {
fs = osfs.New(os.TempDir())
path, err := util.TempDir(fs, "", "")
if err != nil {
panic(err)
}
fs, err = fs.Chroot(path)
if err != nil {
panic(err)
}
clean = func() {
_ = util.RemoveAll(fs, path)
}
return
}
type SuiteCommon struct{}
var _ = Suite(&SuiteCommon{})
var countLinesTests = [...]struct {
i string // the string we want to count lines from
e int // the expected number of lines in i
}{
{"", 0},
{"a", 1},
{"a\n", 1},
{"a\nb", 2},
{"a\nb\n", 2},
{"a\nb\nc", 3},
{"a\nb\nc\n", 3},
{"a\n\n\nb\n", 4},
{"first line\n\tsecond line\nthird line\n", 3},
}
func (s *SuiteCommon) TestCountLines(c *C) {
for i, t := range countLinesTests {
o := countLines(t.i)
c.Assert(o, Equals, t.e, Commentf("subtest %d, input=%q", i, t.i))
}
}
func AssertReferences(c *C, r *Repository, expected map[string]string) {
for name, target := range expected {
expected := plumbing.NewReferenceFromStrings(name, target)
obtained, err := r.Reference(expected.Name(), true)
c.Assert(err, IsNil)
c.Assert(obtained, DeepEquals, expected)
}
}
func AssertReferencesMissing(c *C, r *Repository, expected []string) {
for _, name := range expected {
_, err := r.Reference(plumbing.ReferenceName(name), false)
c.Assert(err, NotNil)
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
}
}
func CommitNewFile(c *C, repo *Repository, fileName string) plumbing.Hash {
wt, err := repo.Worktree()
c.Assert(err, IsNil)
fd, err := wt.Filesystem.Create(fileName)
c.Assert(err, IsNil)
_, err = fd.Write([]byte("# test file"))
c.Assert(err, IsNil)
err = fd.Close()
c.Assert(err, IsNil)
_, err = wt.Add(fileName)
c.Assert(err, IsNil)
sha, err := wt.Commit("test commit", &CommitOptions{
Author: &object.Signature{
Name: "test",
Email: "test@example.com",
When: time.Now(),
},
Committer: &object.Signature{
Name: "test",
Email: "test@example.com",
When: time.Now(),
},
})
c.Assert(err, IsNil)
return sha
}