Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

*: package context support in Repository, Remote and Submodule #509

Merged
merged 1 commit into from
Jul 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 43 additions & 12 deletions remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ func (r *Remote) String() string {
// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if the
// remote was already up-to-date.
func (r *Remote) Push(o *PushOptions) error {
return r.PushContext(context.Background(), o)
}

// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
// the remote was already up-to-date.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error {
// TODO: Sideband support
if err := o.Validate(); err != nil {
return err
Expand Down Expand Up @@ -124,7 +134,7 @@ func (r *Remote) Push(o *PushOptions) error {
return err
}

rs, err := pushHashes(s, r.s, req, hashesToPush)
rs, err := pushHashes(ctx, s, r.s, req, hashesToPush)
if err != nil {
return err
}
Expand Down Expand Up @@ -165,14 +175,30 @@ func (r *Remote) updateRemoteReferenceStorage(
return nil
}

// Fetch fetches references from the remote to the local repository.
// no changes to be fetched and no local references to update, or an error.
func (r *Remote) Fetch(o *FetchOptions) error {
_, err := r.fetch(o)
// FetchContext fetches references along with the objects necessary to complete
// their histories.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error {
_, err := r.fetch(ctx, o)
return err
}

func (r *Remote) fetch(o *FetchOptions) (storer.ReferenceStorer, error) {
// Fetch fetches references along with the objects necessary to complete their
// histories.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
func (r *Remote) Fetch(o *FetchOptions) error {
return r.FetchContext(context.Background(), o)
}

func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (storer.ReferenceStorer, error) {
if o.RemoteName == "" {
o.RemoteName = r.c.Name
}
Expand Down Expand Up @@ -219,7 +245,7 @@ func (r *Remote) fetch(o *FetchOptions) (storer.ReferenceStorer, error) {
return nil, err
}

if err := r.fetchPack(o, s, req); err != nil {
if err := r.fetchPack(ctx, o, s, req); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -268,10 +294,10 @@ func newClient(url string) (transport.Transport, transport.Endpoint, error) {
return c, ep, err
}

func (r *Remote) fetchPack(o *FetchOptions, s transport.UploadPackSession,
func (r *Remote) fetchPack(ctx context.Context, o *FetchOptions, s transport.UploadPackSession,
req *packp.UploadPackRequest) (err error) {

reader, err := s.UploadPack(context.TODO(), req)
reader, err := s.UploadPack(ctx, req)
if err != nil {
return err
}
Expand Down Expand Up @@ -698,8 +724,13 @@ func referencesToHashes(refs storer.ReferenceStorer) ([]plumbing.Hash, error) {
return hs, nil
}

func pushHashes(sess transport.ReceivePackSession, sto storer.EncodedObjectStorer,
req *packp.ReferenceUpdateRequest, hs []plumbing.Hash) (*packp.ReportStatus, error) {
func pushHashes(
ctx context.Context,
sess transport.ReceivePackSession,
sto storer.EncodedObjectStorer,
req *packp.ReferenceUpdateRequest,
hs []plumbing.Hash,
) (*packp.ReportStatus, error) {

rd, wr := io.Pipe()
req.Packfile = rd
Expand All @@ -714,7 +745,7 @@ func pushHashes(sess transport.ReceivePackSession, sto storer.EncodedObjectStore
done <- wr.Close()
}()

rs, err := sess.ReceivePack(context.TODO(), req)
rs, err := sess.ReceivePack(ctx, req)
if err != nil {
return nil, err
}
Expand Down
41 changes: 41 additions & 0 deletions remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package git

import (
"bytes"
"context"
"io"
"io/ioutil"
"os"
Expand Down Expand Up @@ -98,6 +99,23 @@ func (s *RemoteSuite) TestFetch(c *C) {
})
}

func (s *RemoteSuite) TestFetchContext(c *C) {
r := newRemote(memory.NewStorage(), &config.RemoteConfig{
URL: s.GetLocalRepositoryURL(fixtures.ByTag("tags").One()),
})

ctx, cancel := context.WithCancel(context.Background())
cancel()

err := r.FetchContext(ctx, &FetchOptions{
RefSpecs: []config.RefSpec{
config.RefSpec("+refs/heads/master:refs/remotes/origin/master"),
},
})
c.Assert(err, NotNil)

}

func (s *RemoteSuite) TestFetchWithAllTags(c *C) {
r := newRemote(memory.NewStorage(), &config.RemoteConfig{
URL: s.GetLocalRepositoryURL(fixtures.ByTag("tags").One()),
Expand Down Expand Up @@ -340,6 +358,29 @@ func (s *RemoteSuite) TestPushToEmptyRepository(c *C) {

}

func (s *RemoteSuite) TestPushContext(c *C) {
url := c.MkDir()
_, err := PlainInit(url, true)
c.Assert(err, IsNil)

fs := fixtures.ByURL("https://github.com/git-fixtures/tags.git").One().DotGit()
sto, err := filesystem.NewStorage(fs)
c.Assert(err, IsNil)

r := newRemote(sto, &config.RemoteConfig{
Name: DefaultRemoteName,
URL: url,
})

ctx, cancel := context.WithCancel(context.Background())
cancel()

err = r.PushContext(ctx, &PushOptions{
RefSpecs: []config.RefSpec{"refs/tags/*:refs/tags/*"},
})
c.Assert(err, NotNil)
}

func (s *RemoteSuite) TestPushTags(c *C) {
url := c.MkDir()
server, err := PlainInit(url, true)
Expand Down
83 changes: 70 additions & 13 deletions repository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package git

import (
"context"
"errors"
"fmt"
stdioutil "io/ioutil"
Expand Down Expand Up @@ -168,19 +169,36 @@ func Open(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {

// Clone a repository into the given Storer and worktree Filesystem with the
// given options, if worktree is nil a bare repository is created. If the given
// storer is not empty ErrRepositoryAlreadyExists is returned
// storer is not empty ErrRepositoryAlreadyExists is returned.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func Clone(s storage.Storer, worktree billy.Filesystem, o *CloneOptions) (*Repository, error) {
return CloneContext(context.Background(), s, worktree, o)
}

// CloneContext a repository into the given Storer and worktree Filesystem with
// the given options, if worktree is nil a bare repository is created. If the
// given storer is not empty ErrRepositoryAlreadyExists is returned.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func CloneContext(
ctx context.Context, s storage.Storer, worktree billy.Filesystem, o *CloneOptions,
) (*Repository, error) {
r, err := Init(s, worktree)
if err != nil {
return nil, err
}

return r, r.clone(o)
return r, r.clone(ctx, o)
}

// PlainInit create an empty git repository at the given path. isBare defines
// if the repository will have worktree (non-bare) or not (bare), if the path
// is not empty ErrRepositoryAlreadyExists is returned
// is not empty ErrRepositoryAlreadyExists is returned.
func PlainInit(path string, isBare bool) (*Repository, error) {
var wt, dot billy.Filesystem

Expand Down Expand Up @@ -279,14 +297,25 @@ func dotGitFileToOSFilesystem(path string, fs billy.Filesystem) (billy.Filesyste

// PlainClone a repository into the path with the given options, isBare defines
// if the new repository will be bare or normal. If the path is not empty
// ErrRepositoryAlreadyExists is returned
// ErrRepositoryAlreadyExists is returned.
func PlainClone(path string, isBare bool, o *CloneOptions) (*Repository, error) {
return PlainCloneContext(context.Background(), path, isBare, o)
}

// PlainCloneContext a repository into the path with the given options, isBare
// defines if the new repository will be bare or normal. If the path is not empty
// ErrRepositoryAlreadyExists is returned.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOptions) (*Repository, error) {
r, err := PlainInit(path, isBare)
if err != nil {
return nil, err
}

return r, r.clone(o)
return r, r.clone(ctx, o)
}

func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository {
Expand Down Expand Up @@ -372,7 +401,7 @@ func (r *Repository) DeleteRemote(name string) error {
}

// Clone clones a remote repository
func (r *Repository) clone(o *CloneOptions) error {
func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
if err := o.Validate(); err != nil {
return err
}
Expand All @@ -386,7 +415,7 @@ func (r *Repository) clone(o *CloneOptions) error {
return err
}

head, err := r.fetchAndUpdateReferences(&FetchOptions{
head, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
RefSpecs: r.cloneRefSpec(o, c),
Depth: o.Depth,
Auth: o.Auth,
Expand Down Expand Up @@ -469,7 +498,7 @@ func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.Remot
}

func (r *Repository) fetchAndUpdateReferences(
o *FetchOptions, ref plumbing.ReferenceName,
ctx context.Context, o *FetchOptions, ref plumbing.ReferenceName,
) (*plumbing.Reference, error) {

if err := o.Validate(); err != nil {
Expand All @@ -482,7 +511,7 @@ func (r *Repository) fetchAndUpdateReferences(
}

objsUpdated := true
remoteRefs, err := remote.fetch(o)
remoteRefs, err := remote.fetch(ctx, o)
if err == NoErrAlreadyUpToDate {
objsUpdated = false
} else if err != nil {
Expand Down Expand Up @@ -581,10 +610,25 @@ func updateReferenceStorerIfNeeded(
return false, nil
}

// Fetch fetches changes from a remote repository.
// Fetch fetches references along with the objects necessary to complete
// their histories, from the remote named as FetchOptions.RemoteName.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
func (r *Repository) Fetch(o *FetchOptions) error {
return r.FetchContext(context.Background(), o)
}

// FetchContext fetches references along with the objects necessary to complete
// their histories, from the remote named as FetchOptions.RemoteName.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func (r *Repository) FetchContext(ctx context.Context, o *FetchOptions) error {
if err := o.Validate(); err != nil {
return err
}
Expand All @@ -594,11 +638,24 @@ func (r *Repository) Fetch(o *FetchOptions) error {
return err
}

return remote.Fetch(o)
return remote.FetchContext(ctx, o)
}

// Push pushes changes to a remote.
// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if
// the remote was already up-to-date, from the remote named as
// FetchOptions.RemoteName.
func (r *Repository) Push(o *PushOptions) error {
return r.PushContext(context.Background(), o)
}

// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
// the remote was already up-to-date, from the remote named as
// FetchOptions.RemoteName.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error {
if err := o.Validate(); err != nil {
return err
}
Expand All @@ -608,7 +665,7 @@ func (r *Repository) Push(o *PushOptions) error {
return err
}

return remote.Push(o)
return remote.PushContext(ctx, o)
}

// Log returns the commit history from the given LogOptions.
Expand Down
Loading