aboutsummaryrefslogtreecommitdiffstats
path: root/remote_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'remote_test.go')
-rw-r--r--remote_test.go293
1 files changed, 292 insertions, 1 deletions
diff --git a/remote_test.go b/remote_test.go
index 1efc9da..d0c8fa8 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -5,12 +5,16 @@ import (
"context"
"errors"
"io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
"runtime"
"time"
"github.com/go-git/go-git/v5/config"
"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/object"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/storer"
@@ -46,6 +50,12 @@ func (s *RemoteSuite) TestFetchInvalidSchemaEndpoint(c *C) {
c.Assert(err, ErrorMatches, ".*unsupported scheme.*")
}
+func (s *RemoteSuite) TestFetchOverriddenEndpoint(c *C) {
+ r := NewRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"http://perfectly-valid-url.example.com"}})
+ err := r.Fetch(&FetchOptions{RemoteURL: "http://\\"})
+ c.Assert(err, ErrorMatches, ".*invalid character.*")
+}
+
func (s *RemoteSuite) TestFetchInvalidFetchOptions(c *C) {
r := NewRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"qux://foo"}})
invalid := config.RefSpec("^*$ñ")
@@ -591,6 +601,66 @@ func (s *RemoteSuite) TestPushTags(c *C) {
})
}
+func (s *RemoteSuite) TestPushFollowTags(c *C) {
+ url, clean := s.TemporalDir()
+ defer clean()
+
+ server, err := PlainInit(url, true)
+ c.Assert(err, IsNil)
+
+ fs := fixtures.ByURL("https://github.com/git-fixtures/basic.git").One().DotGit()
+ sto := filesystem.NewStorage(fs, cache.NewObjectLRUDefault())
+
+ r := NewRemote(sto, &config.RemoteConfig{
+ Name: DefaultRemoteName,
+ URLs: []string{url},
+ })
+
+ localRepo := newRepository(sto, fs)
+ tipTag, err := localRepo.CreateTag(
+ "tip",
+ plumbing.NewHash("e8d3ffab552895c19b9fcf7aa264d277cde33881"),
+ &CreateTagOptions{
+ Message: "an annotated tag",
+ },
+ )
+ c.Assert(err, IsNil)
+
+ initialTag, err := localRepo.CreateTag(
+ "initial-commit",
+ plumbing.NewHash("b029517f6300c2da0f4b651b8642506cd6aaf45d"),
+ &CreateTagOptions{
+ Message: "a tag for the initial commit",
+ },
+ )
+ c.Assert(err, IsNil)
+
+ _, err = localRepo.CreateTag(
+ "master-tag",
+ plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
+ &CreateTagOptions{
+ Message: "a tag with a commit not reachable from branch",
+ },
+ )
+ c.Assert(err, IsNil)
+
+ err = r.Push(&PushOptions{
+ RefSpecs: []config.RefSpec{"+refs/heads/branch:refs/heads/branch"},
+ FollowTags: true,
+ })
+ c.Assert(err, IsNil)
+
+ AssertReferences(c, server, map[string]string{
+ "refs/heads/branch": "e8d3ffab552895c19b9fcf7aa264d277cde33881",
+ "refs/tags/tip": tipTag.Hash().String(),
+ "refs/tags/initial-commit": initialTag.Hash().String(),
+ })
+
+ AssertReferencesMissing(c, server, []string{
+ "refs/tags/master-tag",
+ })
+}
+
func (s *RemoteSuite) TestPushNoErrAlreadyUpToDate(c *C) {
fs := fixtures.Basic().One().DotGit()
sto := filesystem.NewStorage(fs, cache.NewObjectLRUDefault())
@@ -746,6 +816,133 @@ func (s *RemoteSuite) TestPushForceWithOption(c *C) {
c.Assert(newRef, Not(DeepEquals), oldRef)
}
+func (s *RemoteSuite) TestPushForceWithLease_success(c *C) {
+ testCases := []struct {
+ desc string
+ forceWithLease ForceWithLease
+ }{
+ {
+ desc: "no arguments",
+ forceWithLease: ForceWithLease{},
+ },
+ {
+ desc: "ref name",
+ forceWithLease: ForceWithLease{
+ RefName: plumbing.ReferenceName("refs/heads/branch"),
+ },
+ },
+ {
+ desc: "ref name and sha",
+ forceWithLease: ForceWithLease{
+ RefName: plumbing.ReferenceName("refs/heads/branch"),
+ Hash: plumbing.NewHash("e8d3ffab552895c19b9fcf7aa264d277cde33881"),
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ c.Log("Executing test cases:", tc.desc)
+
+ f := fixtures.Basic().One()
+ sto := filesystem.NewStorage(f.DotGit(), cache.NewObjectLRUDefault())
+ dstFs := f.DotGit()
+ dstSto := filesystem.NewStorage(dstFs, cache.NewObjectLRUDefault())
+
+ newCommit := plumbing.NewHashReference(
+ "refs/heads/branch", plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
+ )
+ c.Assert(sto.SetReference(newCommit), IsNil)
+
+ ref, err := sto.Reference("refs/heads/branch")
+ c.Log(ref.String())
+
+ url := dstFs.Root()
+ r := NewRemote(sto, &config.RemoteConfig{
+ Name: DefaultRemoteName,
+ URLs: []string{url},
+ })
+
+ oldRef, err := dstSto.Reference("refs/heads/branch")
+ c.Assert(err, IsNil)
+ c.Assert(oldRef, NotNil)
+
+ c.Assert(r.Push(&PushOptions{
+ RefSpecs: []config.RefSpec{"refs/heads/branch:refs/heads/branch"},
+ ForceWithLease: &ForceWithLease{},
+ }), IsNil)
+
+ newRef, err := dstSto.Reference("refs/heads/branch")
+ c.Assert(err, IsNil)
+ c.Assert(newRef, DeepEquals, newCommit)
+ }
+}
+
+func (s *RemoteSuite) TestPushForceWithLease_failure(c *C) {
+ testCases := []struct {
+ desc string
+ forceWithLease ForceWithLease
+ }{
+ {
+ desc: "no arguments",
+ forceWithLease: ForceWithLease{},
+ },
+ {
+ desc: "ref name",
+ forceWithLease: ForceWithLease{
+ RefName: plumbing.ReferenceName("refs/heads/branch"),
+ },
+ },
+ {
+ desc: "ref name and sha",
+ forceWithLease: ForceWithLease{
+ RefName: plumbing.ReferenceName("refs/heads/branch"),
+ Hash: plumbing.NewHash("152175bf7e5580299fa1f0ba41ef6474cc043b70"),
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ c.Log("Executing test cases:", tc.desc)
+
+ f := fixtures.Basic().One()
+ sto := filesystem.NewStorage(f.DotGit(), cache.NewObjectLRUDefault())
+ c.Assert(sto.SetReference(
+ plumbing.NewHashReference(
+ "refs/heads/branch", plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
+ ),
+ ), IsNil)
+
+ dstFs := f.DotGit()
+ dstSto := filesystem.NewStorage(dstFs, cache.NewObjectLRUDefault())
+ c.Assert(dstSto.SetReference(
+ plumbing.NewHashReference(
+ "refs/heads/branch", plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc"),
+ ),
+ ), IsNil)
+
+ url := dstFs.Root()
+ r := NewRemote(sto, &config.RemoteConfig{
+ Name: DefaultRemoteName,
+ URLs: []string{url},
+ })
+
+ oldRef, err := dstSto.Reference("refs/heads/branch")
+ c.Assert(err, IsNil)
+ c.Assert(oldRef, NotNil)
+
+ err = r.Push(&PushOptions{
+ RefSpecs: []config.RefSpec{"refs/heads/branch:refs/heads/branch"},
+ ForceWithLease: &ForceWithLease{},
+ })
+
+ c.Assert(err, DeepEquals, errors.New("non-fast-forward update: refs/heads/branch"))
+
+ newRef, err := dstSto.Reference("refs/heads/branch")
+ c.Assert(err, IsNil)
+ c.Assert(newRef, Not(DeepEquals), plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"))
+ }
+}
+
func (s *RemoteSuite) TestPushPrune(c *C) {
fs := fixtures.Basic().One().DotGit()
@@ -805,7 +1002,7 @@ func (s *RemoteSuite) TestPushPrune(c *C) {
"refs/remotes/origin/master": ref.Hash().String(),
})
- ref, err = server.Reference(plumbing.ReferenceName("refs/tags/v1.0.0"), true)
+ _, err = server.Reference(plumbing.ReferenceName("refs/tags/v1.0.0"), true)
c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
}
@@ -903,6 +1100,12 @@ func (s *RemoteSuite) TestPushNonExistentEndpoint(c *C) {
c.Assert(err, NotNil)
}
+func (s *RemoteSuite) TestPushOverriddenEndpoint(c *C) {
+ r := NewRemote(nil, &config.RemoteConfig{Name: "origin", URLs: []string{"http://perfectly-valid-url.example.com"}})
+ err := r.Push(&PushOptions{RemoteURL: "http://\\"})
+ c.Assert(err, ErrorMatches, ".*invalid character.*")
+}
+
func (s *RemoteSuite) TestPushInvalidSchemaEndpoint(c *C) {
r := NewRemote(nil, &config.RemoteConfig{Name: "origin", URLs: []string{"qux://foo"}})
err := r.Push(&PushOptions{})
@@ -1134,3 +1337,91 @@ func (s *RemoteSuite) TestPushRequireRemoteRefs(c *C) {
c.Assert(err, IsNil)
c.Assert(newRef, Not(DeepEquals), oldRef)
}
+
+func (s *RemoteSuite) TestCanPushShasToReference(c *C) {
+ d, err := ioutil.TempDir("", "TestCanPushShasToReference")
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+ defer os.RemoveAll(d)
+
+ // remote currently forces a plain path for path based remotes inside the PushContext function.
+ // This makes it impossible, in the current state to use memfs.
+ // For the sake of readability, use the same osFS everywhere and use plain git repositories on temporary files
+ remote, err := PlainInit(filepath.Join(d, "remote"), true)
+ c.Assert(err, IsNil)
+ c.Assert(remote, NotNil)
+
+ repo, err := PlainInit(filepath.Join(d, "repo"), false)
+ c.Assert(err, IsNil)
+ c.Assert(repo, NotNil)
+
+ fd, err := os.Create(filepath.Join(d, "repo", "README.md"))
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+ _, err = fd.WriteString("# test repo")
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+ err = fd.Close()
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+
+ wt, err := repo.Worktree()
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+
+ wt.Add("README.md")
+ 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)
+ if err != nil {
+ return
+ }
+
+ gitremote, err := repo.CreateRemote(&config.RemoteConfig{
+ Name: "local",
+ URLs: []string{filepath.Join(d, "remote")},
+ })
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+
+ err = gitremote.Push(&PushOptions{
+ RemoteName: "local",
+ RefSpecs: []config.RefSpec{
+ // TODO: check with short hashes that this is still respected
+ config.RefSpec(sha.String() + ":refs/heads/branch"),
+ },
+ })
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+
+ ref, err := remote.Reference(plumbing.ReferenceName("refs/heads/branch"), false)
+ c.Assert(err, IsNil)
+ if err != nil {
+ return
+ }
+ c.Assert(ref.Hash().String(), Equals, sha.String())
+}