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

Commit e19163e

Browse files
authored
Merge pull request #509 from mcuadros/ctx-main
*: package context support in Repository, Remote and Submodule
2 parents d7b898e + 064051f commit e19163e

8 files changed

+300
-66
lines changed

remote.go

+43-12
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ func (r *Remote) String() string {
5252
// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if the
5353
// remote was already up-to-date.
5454
func (r *Remote) Push(o *PushOptions) error {
55+
return r.PushContext(context.Background(), o)
56+
}
57+
58+
// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
59+
// the remote was already up-to-date.
60+
//
61+
// The provided Context must be non-nil. If the context expires before the
62+
// operation is complete, an error is returned. The context only affects to the
63+
// transport operations.
64+
func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error {
5565
// TODO: Sideband support
5666
if err := o.Validate(); err != nil {
5767
return err
@@ -124,7 +134,7 @@ func (r *Remote) Push(o *PushOptions) error {
124134
return err
125135
}
126136

127-
rs, err := pushHashes(s, r.s, req, hashesToPush)
137+
rs, err := pushHashes(ctx, s, r.s, req, hashesToPush)
128138
if err != nil {
129139
return err
130140
}
@@ -165,14 +175,30 @@ func (r *Remote) updateRemoteReferenceStorage(
165175
return nil
166176
}
167177

168-
// Fetch fetches references from the remote to the local repository.
169-
// no changes to be fetched and no local references to update, or an error.
170-
func (r *Remote) Fetch(o *FetchOptions) error {
171-
_, err := r.fetch(o)
178+
// FetchContext fetches references along with the objects necessary to complete
179+
// their histories.
180+
//
181+
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
182+
// no changes to be fetched, or an error.
183+
//
184+
// The provided Context must be non-nil. If the context expires before the
185+
// operation is complete, an error is returned. The context only affects to the
186+
// transport operations.
187+
func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error {
188+
_, err := r.fetch(ctx, o)
172189
return err
173190
}
174191

175-
func (r *Remote) fetch(o *FetchOptions) (storer.ReferenceStorer, error) {
192+
// Fetch fetches references along with the objects necessary to complete their
193+
// histories.
194+
//
195+
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
196+
// no changes to be fetched, or an error.
197+
func (r *Remote) Fetch(o *FetchOptions) error {
198+
return r.FetchContext(context.Background(), o)
199+
}
200+
201+
func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (storer.ReferenceStorer, error) {
176202
if o.RemoteName == "" {
177203
o.RemoteName = r.c.Name
178204
}
@@ -219,7 +245,7 @@ func (r *Remote) fetch(o *FetchOptions) (storer.ReferenceStorer, error) {
219245
return nil, err
220246
}
221247

222-
if err := r.fetchPack(o, s, req); err != nil {
248+
if err := r.fetchPack(ctx, o, s, req); err != nil {
223249
return nil, err
224250
}
225251
}
@@ -268,10 +294,10 @@ func newClient(url string) (transport.Transport, transport.Endpoint, error) {
268294
return c, ep, err
269295
}
270296

271-
func (r *Remote) fetchPack(o *FetchOptions, s transport.UploadPackSession,
297+
func (r *Remote) fetchPack(ctx context.Context, o *FetchOptions, s transport.UploadPackSession,
272298
req *packp.UploadPackRequest) (err error) {
273299

274-
reader, err := s.UploadPack(context.TODO(), req)
300+
reader, err := s.UploadPack(ctx, req)
275301
if err != nil {
276302
return err
277303
}
@@ -698,8 +724,13 @@ func referencesToHashes(refs storer.ReferenceStorer) ([]plumbing.Hash, error) {
698724
return hs, nil
699725
}
700726

701-
func pushHashes(sess transport.ReceivePackSession, sto storer.EncodedObjectStorer,
702-
req *packp.ReferenceUpdateRequest, hs []plumbing.Hash) (*packp.ReportStatus, error) {
727+
func pushHashes(
728+
ctx context.Context,
729+
sess transport.ReceivePackSession,
730+
sto storer.EncodedObjectStorer,
731+
req *packp.ReferenceUpdateRequest,
732+
hs []plumbing.Hash,
733+
) (*packp.ReportStatus, error) {
703734

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

717-
rs, err := sess.ReceivePack(context.TODO(), req)
748+
rs, err := sess.ReceivePack(ctx, req)
718749
if err != nil {
719750
return nil, err
720751
}

remote_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package git
22

33
import (
44
"bytes"
5+
"context"
56
"io"
67
"io/ioutil"
78
"os"
@@ -98,6 +99,23 @@ func (s *RemoteSuite) TestFetch(c *C) {
9899
})
99100
}
100101

102+
func (s *RemoteSuite) TestFetchContext(c *C) {
103+
r := newRemote(memory.NewStorage(), &config.RemoteConfig{
104+
URL: s.GetLocalRepositoryURL(fixtures.ByTag("tags").One()),
105+
})
106+
107+
ctx, cancel := context.WithCancel(context.Background())
108+
cancel()
109+
110+
err := r.FetchContext(ctx, &FetchOptions{
111+
RefSpecs: []config.RefSpec{
112+
config.RefSpec("+refs/heads/master:refs/remotes/origin/master"),
113+
},
114+
})
115+
c.Assert(err, NotNil)
116+
117+
}
118+
101119
func (s *RemoteSuite) TestFetchWithAllTags(c *C) {
102120
r := newRemote(memory.NewStorage(), &config.RemoteConfig{
103121
URL: s.GetLocalRepositoryURL(fixtures.ByTag("tags").One()),
@@ -340,6 +358,29 @@ func (s *RemoteSuite) TestPushToEmptyRepository(c *C) {
340358

341359
}
342360

361+
func (s *RemoteSuite) TestPushContext(c *C) {
362+
url := c.MkDir()
363+
_, err := PlainInit(url, true)
364+
c.Assert(err, IsNil)
365+
366+
fs := fixtures.ByURL("https://github.com/git-fixtures/tags.git").One().DotGit()
367+
sto, err := filesystem.NewStorage(fs)
368+
c.Assert(err, IsNil)
369+
370+
r := newRemote(sto, &config.RemoteConfig{
371+
Name: DefaultRemoteName,
372+
URL: url,
373+
})
374+
375+
ctx, cancel := context.WithCancel(context.Background())
376+
cancel()
377+
378+
err = r.PushContext(ctx, &PushOptions{
379+
RefSpecs: []config.RefSpec{"refs/tags/*:refs/tags/*"},
380+
})
381+
c.Assert(err, NotNil)
382+
}
383+
343384
func (s *RemoteSuite) TestPushTags(c *C) {
344385
url := c.MkDir()
345386
server, err := PlainInit(url, true)

repository.go

+70-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package git
22

33
import (
4+
"context"
45
"errors"
56
"fmt"
67
stdioutil "io/ioutil"
@@ -168,19 +169,36 @@ func Open(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
168169

169170
// Clone a repository into the given Storer and worktree Filesystem with the
170171
// given options, if worktree is nil a bare repository is created. If the given
171-
// storer is not empty ErrRepositoryAlreadyExists is returned
172+
// storer is not empty ErrRepositoryAlreadyExists is returned.
173+
//
174+
// The provided Context must be non-nil. If the context expires before the
175+
// operation is complete, an error is returned. The context only affects to the
176+
// transport operations.
172177
func Clone(s storage.Storer, worktree billy.Filesystem, o *CloneOptions) (*Repository, error) {
178+
return CloneContext(context.Background(), s, worktree, o)
179+
}
180+
181+
// CloneContext a repository into the given Storer and worktree Filesystem with
182+
// the given options, if worktree is nil a bare repository is created. If the
183+
// given storer is not empty ErrRepositoryAlreadyExists is returned.
184+
//
185+
// The provided Context must be non-nil. If the context expires before the
186+
// operation is complete, an error is returned. The context only affects to the
187+
// transport operations.
188+
func CloneContext(
189+
ctx context.Context, s storage.Storer, worktree billy.Filesystem, o *CloneOptions,
190+
) (*Repository, error) {
173191
r, err := Init(s, worktree)
174192
if err != nil {
175193
return nil, err
176194
}
177195

178-
return r, r.clone(o)
196+
return r, r.clone(ctx, o)
179197
}
180198

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

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

280298
// PlainClone a repository into the path with the given options, isBare defines
281299
// if the new repository will be bare or normal. If the path is not empty
282-
// ErrRepositoryAlreadyExists is returned
300+
// ErrRepositoryAlreadyExists is returned.
283301
func PlainClone(path string, isBare bool, o *CloneOptions) (*Repository, error) {
302+
return PlainCloneContext(context.Background(), path, isBare, o)
303+
}
304+
305+
// PlainCloneContext a repository into the path with the given options, isBare
306+
// defines if the new repository will be bare or normal. If the path is not empty
307+
// ErrRepositoryAlreadyExists is returned.
308+
//
309+
// The provided Context must be non-nil. If the context expires before the
310+
// operation is complete, an error is returned. The context only affects to the
311+
// transport operations.
312+
func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOptions) (*Repository, error) {
284313
r, err := PlainInit(path, isBare)
285314
if err != nil {
286315
return nil, err
287316
}
288317

289-
return r, r.clone(o)
318+
return r, r.clone(ctx, o)
290319
}
291320

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

374403
// Clone clones a remote repository
375-
func (r *Repository) clone(o *CloneOptions) error {
404+
func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
376405
if err := o.Validate(); err != nil {
377406
return err
378407
}
@@ -386,7 +415,7 @@ func (r *Repository) clone(o *CloneOptions) error {
386415
return err
387416
}
388417

389-
head, err := r.fetchAndUpdateReferences(&FetchOptions{
418+
head, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
390419
RefSpecs: r.cloneRefSpec(o, c),
391420
Depth: o.Depth,
392421
Auth: o.Auth,
@@ -469,7 +498,7 @@ func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.Remot
469498
}
470499

471500
func (r *Repository) fetchAndUpdateReferences(
472-
o *FetchOptions, ref plumbing.ReferenceName,
501+
ctx context.Context, o *FetchOptions, ref plumbing.ReferenceName,
473502
) (*plumbing.Reference, error) {
474503

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

484513
objsUpdated := true
485-
remoteRefs, err := remote.fetch(o)
514+
remoteRefs, err := remote.fetch(ctx, o)
486515
if err == NoErrAlreadyUpToDate {
487516
objsUpdated = false
488517
} else if err != nil {
@@ -581,10 +610,25 @@ func updateReferenceStorerIfNeeded(
581610
return false, nil
582611
}
583612

584-
// Fetch fetches changes from a remote repository.
613+
// Fetch fetches references along with the objects necessary to complete
614+
// their histories, from the remote named as FetchOptions.RemoteName.
615+
//
585616
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
586617
// no changes to be fetched, or an error.
587618
func (r *Repository) Fetch(o *FetchOptions) error {
619+
return r.FetchContext(context.Background(), o)
620+
}
621+
622+
// FetchContext fetches references along with the objects necessary to complete
623+
// their histories, from the remote named as FetchOptions.RemoteName.
624+
//
625+
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
626+
// no changes to be fetched, or an error.
627+
//
628+
// The provided Context must be non-nil. If the context expires before the
629+
// operation is complete, an error is returned. The context only affects to the
630+
// transport operations.
631+
func (r *Repository) FetchContext(ctx context.Context, o *FetchOptions) error {
588632
if err := o.Validate(); err != nil {
589633
return err
590634
}
@@ -594,11 +638,24 @@ func (r *Repository) Fetch(o *FetchOptions) error {
594638
return err
595639
}
596640

597-
return remote.Fetch(o)
641+
return remote.FetchContext(ctx, o)
598642
}
599643

600-
// Push pushes changes to a remote.
644+
// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if
645+
// the remote was already up-to-date, from the remote named as
646+
// FetchOptions.RemoteName.
601647
func (r *Repository) Push(o *PushOptions) error {
648+
return r.PushContext(context.Background(), o)
649+
}
650+
651+
// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
652+
// the remote was already up-to-date, from the remote named as
653+
// FetchOptions.RemoteName.
654+
//
655+
// The provided Context must be non-nil. If the context expires before the
656+
// operation is complete, an error is returned. The context only affects to the
657+
// transport operations.
658+
func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error {
602659
if err := o.Validate(); err != nil {
603660
return err
604661
}
@@ -608,7 +665,7 @@ func (r *Repository) Push(o *PushOptions) error {
608665
return err
609666
}
610667

611-
return remote.Push(o)
668+
return remote.PushContext(ctx, o)
612669
}
613670

614671
// Log returns the commit history from the given LogOptions.

0 commit comments

Comments
 (0)