diff options
author | Thibault Jamet <tjamet@users.noreply.github.com> | 2021-05-26 14:19:07 +0200 |
---|---|---|
committer | Thibault Jamet <tjamet@users.noreply.github.com> | 2021-10-28 21:48:32 +0200 |
commit | 617ae9f34f46b440f59979cdfc8a399e36decc32 (patch) | |
tree | 5df11cb3a89b88e51ca924feb35d579c06ff6c71 /remote_test.go | |
parent | 99457e570d34320b12fb4fcd0f054f3d0b1d3eec (diff) | |
download | go-git-617ae9f34f46b440f59979cdfc8a399e36decc32.tar.gz |
Add support to push commits per hashes
Using plain git, the command `git push ${sha}:refs/heads/some-branch`
actually ensures that the remote branch `some-branch` points to the
commit `${sha}`.
In the current version of go-git, this results in an "everything is
up to date" error.
When a source reference is not found, check the object storage to find
the sha. If it is found, consider pushing this exact commit.
fixes: #105
Diffstat (limited to 'remote_test.go')
-rw-r--r-- | remote_test.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/remote_test.go b/remote_test.go index 0283e64..df07c08 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" @@ -1206,3 +1210,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()) +} |