package git
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/fixtures"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
"gopkg.in/src-d/go-git.v4/storage/memory"
. "gopkg.in/check.v1"
"gopkg.in/src-d/go-git.v4/storage/filesystem"
)
type RepositorySuite struct {
BaseSuite
}
var _ = Suite(&RepositorySuite{})
func (s *RepositorySuite) TestNewRepository(c *C) {
r := NewMemoryRepository()
c.Assert(r, NotNil)
}
func (s *RepositorySuite) TestCreateRemoteAndRemote(c *C) {
r := NewMemoryRepository()
remote, err := r.CreateRemote(&config.RemoteConfig{
Name: "foo",
URL: "http://foo/foo.git",
})
c.Assert(err, IsNil)
c.Assert(remote.Config().Name, Equals, "foo")
alt, err := r.Remote("foo")
c.Assert(err, IsNil)
c.Assert(alt, Not(Equals), remote)
c.Assert(alt.Config().Name, Equals, "foo")
}
func (s *RepositorySuite) TestRemoteWithProgress(c *C) {
buf := bytes.NewBuffer(nil)
r := NewMemoryRepository()
r.Progress = buf
remote, err := r.CreateRemote(&config.RemoteConfig{
Name: "foo",
URL: "http://foo/foo.git",
})
c.Assert(err, IsNil)
c.Assert(remote.p, Equals, buf)
}
func (s *RepositorySuite) TestCreateRemoteInvalid(c *C) {
r := NewMemoryRepository()
remote, err := r.CreateRemote(&config.RemoteConfig{})
c.Assert(err, Equals, config.ErrRemoteConfigEmptyName)
c.Assert(remote, IsNil)
}
func (s *RepositorySuite) TestDeleteRemote(c *C) {
r := NewMemoryRepository()
_, err := r.CreateRemote(&config.RemoteConfig{
Name: "foo",
URL: "http://foo/foo.git",
})
c.Assert(err, IsNil)
err = r.DeleteRemote("foo")
c.Assert(err, IsNil)
alt, err := r.Remote("foo")
c.Assert(err, Equals, ErrRemoteNotFound)
c.Assert(alt, IsNil)
}
func (s *RepositorySuite) TestFetch(c *C) {
r := NewMemoryRepository()
_, err := r.CreateRemote(&config.RemoteConfig{
Name: DefaultRemoteName,
URL: s.GetBasicLocalRepositoryURL(),
})
c.Assert(err, IsNil)
c.Assert(r.Fetch(&FetchOptions{}), IsNil)
remotes, err := r.Remotes()
c.Assert(err, IsNil)
c.Assert(remotes, HasLen, 1)
_, err = r.Reference(plumbing.HEAD, false)
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
branch, err := r.Reference("refs/remotes/origin/master", false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Type(), Equals, plumbing.HashReference)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
}
func (s *RepositorySuite) TestClone(c *C) {
r := NewMemoryRepository()
head, err := r.Head()
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
c.Assert(head, IsNil)
err = r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
})
c.Assert(err, IsNil)
remotes, err := r.Remotes()
c.Assert(err, IsNil)
c.Assert(remotes, HasLen, 1)
head, err = r.Reference(plumbing.HEAD, false)
c.Assert(err, IsNil)
c.Assert(head, NotNil)
c.Assert(head.Type(), Equals, plumbing.SymbolicReference)
c.Assert(head.Target().String(), Equals, "refs/heads/master")
branch, err := r.Reference(head.Target(), false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
branch, err = r.Reference("refs/remotes/origin/master", false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Type(), Equals, plumbing.HashReference)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
}
func (s *RepositorySuite) TestCloneConfig(c *C) {
r := NewMemoryRepository()
head, err := r.Head()
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
c.Assert(head, IsNil)
err = r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
})
c.Assert(err, IsNil)
cfg, err := r.Config()
c.Assert(err, IsNil)
c.Assert(cfg.Core.IsBare, Equals, true)
c.Assert(cfg.Remotes, HasLen, 1)
c.Assert(cfg.Remotes["origin"].Name, Equals, "origin")
c.Assert(cfg.Remotes["origin"].URL, Not(Equals), "")
}
func (s *RepositorySuite) TestCloneNonEmpty(c *C) {
r := NewMemoryRepository()
head, err := r.Head()
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
c.Assert(head, IsNil)
o := &CloneOptions{URL: s.GetBasicLocalRepositoryURL()}
err = r.Clone(o)
c.Assert(err, IsNil)
err = r.Clone(o)
c.Assert(err, Equals, ErrRepositoryNonEmpty)
}
func (s *RepositorySuite) TestCloneSingleBranchAndNonHEAD(c *C) {
r := NewMemoryRepository()
head, err := r.Head()
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
c.Assert(head, IsNil)
err = r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
ReferenceName: plumbing.ReferenceName("refs/heads/branch"),
SingleBranch: true,
})
c.Assert(err, IsNil)
remotes, err := r.Remotes()
c.Assert(err, IsNil)
c.Assert(remotes, HasLen, 1)
head, err = r.Reference(plumbing.HEAD, false)
c.Assert(err, IsNil)
c.Assert(head, NotNil)
c.Assert(head.Type(), Equals, plumbing.SymbolicReference)
c.Assert(head.Target().String(), Equals, "refs/heads/branch")
branch, err := r.Reference(head.Target(), false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
branch, err = r.Reference("refs/remotes/origin/branch", false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Type(), Equals, plumbing.HashReference)
c.Assert(branch.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
}
func (s *RepositorySuite) TestCloneSingleBranch(c *C) {
r := NewMemoryRepository()
head, err := r.Head()
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
c.Assert(head, IsNil)
err = r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
SingleBranch: true,
})
c.Assert(err, IsNil)
remotes, err := r.Remotes()
c.Assert(err, IsNil)
c.Assert(remotes, HasLen, 1)
head, err = r.Reference(plumbing.HEAD, false)
c.Assert(err, IsNil)
c.Assert(head, NotNil)
c.Assert(head.Type(), Equals, plumbing.SymbolicReference)
c.Assert(head.Target().String(), Equals, "refs/heads/master")
branch, err := r.Reference(head.Target(), false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
branch, err = r.Reference("refs/remotes/origin/master", false)
c.Assert(err, IsNil)
c.Assert(branch, NotNil)
c.Assert(branch.Type(), Equals, plumbing.HashReference)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
}
func (s *RepositorySuite) TestCloneDetachedHEAD(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
ReferenceName: plumbing.ReferenceName("refs/tags/v1.0.0"),
})
head, err := r.Reference(plumbing.HEAD, false)
c.Assert(err, IsNil)
c.Assert(head, NotNil)
c.Assert(head.Type(), Equals, plumbing.HashReference)
c.Assert(head.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
}
func (s *RepositorySuite) TestPullSingleBranch(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
SingleBranch: true,
})
c.Assert(err, IsNil)
err = r.Pull(&PullOptions{})
c.Assert(err, Equals, NoErrAlreadyUpToDate)
branch, err := r.Reference("refs/heads/master", false)
c.Assert(err, IsNil)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
branch, err = r.Reference("refs/remotes/foo/branch", false)
c.Assert(err, NotNil)
storage := r.s.(*memory.Storage)
c.Assert(storage.Objects, HasLen, 28)
}
func (s *RepositorySuite) TestPullA(c *C) {
path := fixtures.Basic().One().Worktree().Base()
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{
URL: fmt.Sprintf("file://%s", filepath.Join(path, ".git")),
})
c.Assert(err, IsNil)
storage := r.s.(*memory.Storage)
c.Assert(storage.Objects, HasLen, 31)
branch, err := r.Reference("refs/heads/master", false)
c.Assert(err, IsNil)
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
branch, err = r.Reference("refs/remotes/origin/branch", false)
c.Assert(err, IsNil)
c.Assert(branch.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
ExecuteOnPath(c, path,
"touch foo",
"git add foo",
"git commit -m foo foo",
)
err = r.Pull(&PullOptions{RemoteName: "origin"})
c.Assert(err, IsNil)
// the commit command has introduced a new commit, tree and blob
c.Assert(storage.Objects, HasLen, 34)
branch, err = r.Reference("refs/heads/master", false)
c.Assert(err, IsNil)
c.Assert(branch.Hash().String(), Not(Equals), "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
// the commit command, was in the local branch, so the remote should be read ok
branch, err = r.Reference("refs/remotes/origin/branch", false)
c.Assert(err, IsNil)
c.Assert(branch.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
}
func (s *RepositorySuite) TestPushToEmptyRepository(c *C) {
srcFs := fixtures.Basic().One().DotGit()
sto, err := filesystem.NewStorage(srcFs)
c.Assert(err, IsNil)
dstFs := fixtures.ByTag("empty").One().DotGit()
url := fmt.Sprintf("file://%s", dstFs.Base())
r, err := NewRepository(sto)
c.Assert(err, IsNil)
_, err = r.CreateRemote(&config.RemoteConfig{
Name: "myremote",
URL: url,
})
c.Assert(err, IsNil)
err = r.Push(&PushOptions{RemoteName: "myremote"})
c.Assert(err, IsNil)
sto, err = filesystem.NewStorage(dstFs)
c.Assert(err, IsNil)
dstRepo, err := NewRepository(sto)
c.Assert(err, IsNil)
iter, err := sto.IterReferences()
c.Assert(err, IsNil)
err = iter.ForEach(func(ref *plumbing.Reference) error {
if !ref.IsBranch() {
return nil
}
dstRef, err := dstRepo.Reference(ref.Name(), true)
c.Assert(err, IsNil)
c.Assert(dstRef, DeepEquals, ref)
return nil
})
c.Assert(err, IsNil)
}
func (s *RepositorySuite) TestPushNonExistentRemote(c *C) {
srcFs := fixtures.Basic().One().DotGit()
sto, err := filesystem.NewStorage(srcFs)
c.Assert(err, IsNil)
r, err := NewRepository(sto)
c.Assert(err, IsNil)
err = r.Push(&PushOptions{RemoteName: "myremote"})
c.Assert(err, ErrorMatches, ".*remote not found.*")
}
func (s *RepositorySuite) TestIsEmpty(c *C) {
r := NewMemoryRepository()
empty, err := r.IsEmpty()
c.Assert(err, IsNil)
c.Assert(empty, Equals, true)
err = r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
empty, err = r.IsEmpty()
c.Assert(err, IsNil)
c.Assert(empty, Equals, false)
}
func (s *RepositorySuite) TestCommit(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{
URL: s.GetBasicLocalRepositoryURL(),
})
c.Assert(err, IsNil)
hash := plumbing.NewHash("b8e471f58bcbca63b07bda20e428190409c2db47")
commit, err := r.Commit(hash)
c.Assert(err, IsNil)
c.Assert(commit.Hash.IsZero(), Equals, false)
c.Assert(commit.Hash, Equals, commit.ID())
c.Assert(commit.Hash, Equals, hash)
c.Assert(commit.Type(), Equals, plumbing.CommitObject)
tree, err := commit.Tree()
c.Assert(err, IsNil)
c.Assert(tree.Hash.IsZero(), Equals, false)
c.Assert(commit.Author.Email, Equals, "daniel@lordran.local")
}
func (s *RepositorySuite) TestCommits(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
count := 0
commits, err := r.Commits()
c.Assert(err, IsNil)
for {
commit, err := commits.Next()
if err != nil {
break
}
count++
c.Assert(commit.Hash.IsZero(), Equals, false)
c.Assert(commit.Hash, Equals, commit.ID())
c.Assert(commit.Type(), Equals, plumbing.CommitObject)
}
c.Assert(count, Equals, 9)
}
func (s *RepositorySuite) TestTag(c *C) {
url := s.GetLocalRepositoryURL(
fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(),
)
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: url})
c.Assert(err, IsNil)
hash := plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")
tag, err := r.Tag(hash)
c.Assert(err, IsNil)
c.Assert(tag.Hash.IsZero(), Equals, false)
c.Assert(tag.Hash, Equals, hash)
c.Assert(tag.Type(), Equals, plumbing.TagObject)
}
func (s *RepositorySuite) TestTags(c *C) {
url := s.GetLocalRepositoryURL(
fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(),
)
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: url})
c.Assert(err, IsNil)
count := 0
tags, err := r.Tags()
c.Assert(err, IsNil)
tags.ForEach(func(tag *object.Tag) error {
count++
c.Assert(tag.Hash.IsZero(), Equals, false)
c.Assert(tag.Type(), Equals, plumbing.TagObject)
return nil
})
refs, _ := r.References()
refs.ForEach(func(ref *plumbing.Reference) error {
return nil
})
c.Assert(count, Equals, 4)
}
func (s *RepositorySuite) TestCommitIterClosePanic(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
commits, err := r.Commits()
c.Assert(err, IsNil)
commits.Close()
}
func (s *RepositorySuite) TestRef(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
ref, err := r.Reference(plumbing.HEAD, false)
c.Assert(err, IsNil)
c.Assert(ref.Name(), Equals, plumbing.HEAD)
ref, err = r.Reference(plumbing.HEAD, true)
c.Assert(err, IsNil)
c.Assert(ref.Name(), Equals, plumbing.ReferenceName("refs/heads/master"))
}
func (s *RepositorySuite) TestRefs(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
c.Assert(err, IsNil)
iter, err := r.References()
c.Assert(err, IsNil)
c.Assert(iter, NotNil)
}
func (s *RepositorySuite) TestObject(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
hash := plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
o, err := r.Object(plumbing.CommitObject, hash)
c.Assert(err, IsNil)
c.Assert(o.ID().IsZero(), Equals, false)
c.Assert(o.Type(), Equals, plumbing.CommitObject)
}
func (s *RepositorySuite) TestObjectNotFound(c *C) {
r := NewMemoryRepository()
err := r.Clone(&CloneOptions{URL: s.GetBasicLocalRepositoryURL()})
c.Assert(err, IsNil)
hash := plumbing.NewHash("0a3fb06ff80156fb153bcdcc58b5e16c2d27625c")
tag, err := r.Object(plumbing.TagObject, hash)
c.Assert(err, DeepEquals, plumbing.ErrObjectNotFound)
c.Assert(tag, IsNil)
}
func ExecuteOnPath(c *C, path string, cmds ...string) error {
for _, cmd := range cmds {
err := executeOnPath(path, cmd)
c.Assert(err, IsNil)
}
return nil
}
func executeOnPath(path, cmd string) error {
args := strings.Split(cmd, " ")
c := exec.Command(args[0], args[1:]...)
c.Dir = path
c.Env = os.Environ()
buf := bytes.NewBuffer(nil)
c.Stderr = buf
c.Stdout = buf
//defer func() { fmt.Println(buf.String()) }()
return c.Run()
}