diff options
-rw-r--r-- | common_test.go | 14 | ||||
-rw-r--r-- | core/reference.go | 14 | ||||
-rw-r--r-- | core/reference_test.go | 7 | ||||
-rw-r--r-- | objects_test.go | 11 | ||||
-rw-r--r-- | options.go | 14 | ||||
-rw-r--r-- | remote.go | 24 | ||||
-rw-r--r-- | remote_test.go | 82 | ||||
-rw-r--r-- | repository.go | 45 | ||||
-rw-r--r-- | repository_test.go | 135 |
9 files changed, 226 insertions, 120 deletions
diff --git a/common_test.go b/common_test.go index f7416e0..e0d11b5 100644 --- a/common_test.go +++ b/common_test.go @@ -20,7 +20,9 @@ func Test(t *testing.T) { TestingT(t) } type BaseSuite struct{} func (s *BaseSuite) SetUpTest(c *C) { - clients.InstallProtocol("mock", &MockGitUploadPackService{}) + clients.InstallProtocol("mock", func(end common.Endpoint) common.GitUploadPackService { + return &MockGitUploadPackService{conected: end} + }) } const RepositoryFixture = "mock://formats/packfile/fixtures/git-fixture.ref-delta" @@ -30,15 +32,11 @@ type MockGitUploadPackService struct { auth common.AuthMethod } -func (p *MockGitUploadPackService) Connect(url common.Endpoint) error { - p.conected = url +func (p *MockGitUploadPackService) Connect() error { return nil } -func (p *MockGitUploadPackService) ConnectWithAuth( - url common.Endpoint, auth common.AuthMethod, -) error { - p.conected = url +func (p *MockGitUploadPackService) ConnectWithAuth(auth common.AuthMethod) error { p.auth = auth return nil } @@ -50,11 +48,13 @@ func (p *MockGitUploadPackService) Info() (*common.GitUploadPackInfo, error) { c.Decode("6ecf0ef2c2dffb796033e5a02219af86ec6584e5 HEADmulti_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done symref=HEAD:refs/heads/master agent=git/2:2.4.8~dbussink-fix-enterprise-tokens-compilation-1167-gc7006cf") ref := core.ReferenceName("refs/heads/master") + tag := core.ReferenceName("refs/tags/v1.0.0") return &common.GitUploadPackInfo{ Capabilities: c, Refs: map[core.ReferenceName]*core.Reference{ core.HEAD: core.NewSymbolicReference(core.HEAD, ref), ref: core.NewHashReference(ref, h), + tag: core.NewHashReference(tag, h), }, }, nil } diff --git a/core/reference.go b/core/reference.go index 4be4971..7d3f378 100644 --- a/core/reference.go +++ b/core/reference.go @@ -34,6 +34,20 @@ const ( // ReferenceName reference name's type ReferenceName string +// AsRemote returns a new remote reference name using current one as base +func (r ReferenceName) AsRemote(remote string) ReferenceName { + return ReferenceName(refRemotePrefix + remote + "/" + r.alias()) +} + +func (r ReferenceName) String() string { + return string(r) +} + +func (r ReferenceName) alias() string { + parts := strings.Split(string(r), "/") + return parts[len(parts)-1] +} + const ( HEAD ReferenceName = "HEAD" ) diff --git a/core/reference_test.go b/core/reference_test.go index 05d20b4..5d88f0e 100644 --- a/core/reference_test.go +++ b/core/reference_test.go @@ -10,6 +10,13 @@ const ( ExampleReferenceName ReferenceName = "refs/heads/v4" ) +func (s *ReferenceSuite) TestReferenceNameAsRemote(c *C) { + c.Assert( + ExampleReferenceName.AsRemote("foo").String(), + Equals, "refs/remotes/foo/v4", + ) +} + func (s *ReferenceSuite) TestNewReferenceFromStrings(c *C) { r := NewReferenceFromStrings("refs/heads/v4", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") c.Assert(r.Type(), Equals, HashReference) diff --git a/objects_test.go b/objects_test.go index aeaceea..d24aa7b 100644 --- a/objects_test.go +++ b/objects_test.go @@ -10,23 +10,22 @@ import ( ) type ObjectsSuite struct { + BaseSuite r *Repository } var _ = Suite(&ObjectsSuite{}) -/* func (s *ObjectsSuite) SetUpTest(c *C) { + s.BaseSuite.SetUpTest(c) + var err error - s.r, err = NewRepository(RepositoryFixture, nil) + s.r, err = NewMemoryRepository() c.Assert(err, IsNil) - s.r.Remotes["origin"].upSrv = &MockGitUploadPackService{} - - err = s.r.Pull("origin", "refs/heads/master") + err = s.r.Clone(&CloneOptions{URL: RepositoryFixture}) c.Assert(err, IsNil) } -*/ func (s *ObjectsSuite) TestNewCommit(c *C) { hash := core.NewHash("a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69") @@ -11,6 +11,14 @@ type CloneOptions struct { URL string // Auth credentials, if required, to uses with the remote repository Auth common.AuthMethod + // Remote branch to fetch + ReferenceName core.ReferenceName +} + +func (o *CloneOptions) Default() { + if o.ReferenceName == "" { + o.ReferenceName = core.HEAD + } } // FetchOptions describe how a fetch should be perform @@ -18,3 +26,9 @@ type FetchOptions struct { // Remote branch to fetch ReferenceName core.ReferenceName } + +func (o *FetchOptions) Default() { + if o.ReferenceName == "" { + o.ReferenceName = core.HEAD + } +} @@ -24,17 +24,18 @@ func NewRemote(url string) (*Remote, error) { // NewAuthenticatedRemote returns a new Remote using the given AuthMethod, using as // client http.DefaultClient func NewAuthenticatedRemote(url string, auth common.AuthMethod) (*Remote, error) { - end, err := common.NewEndpoint(url) + endpoint, err := common.NewEndpoint(url) if err != nil { return nil, err } - upSrv, err := clients.NewGitUploadPackService(url) + upSrv, err := clients.NewGitUploadPackService(endpoint) if err != nil { return nil, err } + return &Remote{ - Endpoint: end, + Endpoint: endpoint, Auth: auth, upSrv: upSrv, }, nil @@ -44,9 +45,9 @@ func NewAuthenticatedRemote(url string, auth common.AuthMethod) (*Remote, error) func (r *Remote) Connect() error { var err error if r.Auth == nil { - err = r.upSrv.Connect(r.Endpoint) + err = r.upSrv.Connect() } else { - err = r.upSrv.ConnectWithAuth(r.Endpoint, r.Auth) + err = r.upSrv.ConnectWithAuth(r.Auth) } if err != nil { @@ -76,26 +77,27 @@ func (r *Remote) Capabilities() *common.Capabilities { } // Fetch returns a reader using the request -func (r *Remote) Fetch(s core.ObjectStorage, o *FetchOptions) (h core.Hash, err error) { +func (r *Remote) Fetch(s core.ObjectStorage, o *FetchOptions) (err error) { + o.Default() + ref, err := r.Ref(o.ReferenceName, true) if err != nil { - return core.ZeroHash, err + return err } - h = ref.Hash() req := &common.GitUploadPackRequest{} - req.Want(h) + req.Want(ref.Hash()) reader, err := r.upSrv.Fetch(req) if err != nil { - return core.ZeroHash, err + return err } defer checkClose(reader, &err) stream := packfile.NewStream(reader) d := packfile.NewDecoder(stream) - return h, d.Decode(s) + return d.Decode(s) } // Head returns the Reference of the HEAD diff --git a/remote_test.go b/remote_test.go index df93b59..798d75d 100644 --- a/remote_test.go +++ b/remote_test.go @@ -3,6 +3,7 @@ package git import ( "gopkg.in/src-d/go-git.v4/clients/http" "gopkg.in/src-d/go-git.v4/core" + "gopkg.in/src-d/go-git.v4/storage/memory" . "gopkg.in/check.v1" ) @@ -13,10 +14,29 @@ type RemoteSuite struct { var _ = Suite(&RemoteSuite{}) +func (s *RemoteSuite) TestNewRemote(c *C) { + r, err := NewRemote(RepositoryFixture) + c.Assert(err, IsNil) + c.Assert(r.Endpoint.String(), Equals, RepositoryFixture) +} + +func (s *RemoteSuite) TestNewRemoteInvalidEndpoint(c *C) { + r, err := NewRemote("qux") + c.Assert(err, NotNil) + c.Assert(r, IsNil) +} + +func (s *RemoteSuite) TestNewRemoteInvalidSchemaEndpoint(c *C) { + r, err := NewRemote("qux://foo") + c.Assert(err, NotNil) + c.Assert(r, IsNil) +} + func (s *RemoteSuite) TestNewAuthenticatedRemote(c *C) { a := &http.BasicAuth{} r, err := NewAuthenticatedRemote(RepositoryFixture, a) c.Assert(err, IsNil) + c.Assert(r.Endpoint.String(), Equals, RepositoryFixture) c.Assert(r.Auth, Equals, a) } @@ -26,6 +46,15 @@ func (s *RemoteSuite) TestConnect(c *C) { c.Assert(r.Connect(), IsNil) } +func (s *RemoteSuite) TestInfo(c *C) { + r, err := NewRemote(RepositoryFixture) + c.Assert(err, IsNil) + c.Assert(r.Info(), IsNil) + c.Assert(r.Connect(), IsNil) + c.Assert(r.Info(), NotNil) + c.Assert(r.Info().Capabilities.Get("ofs-delta"), NotNil) +} + func (s *RemoteSuite) TestDefaultBranch(c *C) { r, err := NewRemote(RepositoryFixture) r.upSrv = &MockGitUploadPackService{} @@ -44,7 +73,6 @@ func (s *RemoteSuite) TestCapabilities(c *C) { c.Assert(r.Capabilities().Get("agent").Values, HasLen, 1) } -/* func (s *RemoteSuite) TestFetch(c *C) { r, err := NewRemote(RepositoryFixture) r.upSrv = &MockGitUploadPackService{} @@ -52,31 +80,63 @@ func (s *RemoteSuite) TestFetch(c *C) { c.Assert(err, IsNil) c.Assert(r.Connect(), IsNil) - req := &common.GitUploadPackRequest{} - req.Want(r.Head().Hash()) + sto := memory.NewObjectStorage() + err = r.Fetch(sto, &FetchOptions{ + ReferenceName: core.HEAD, + }) - reader, err := r.Fetch(req) c.Assert(err, IsNil) + c.Assert(sto.Objects, HasLen, 28) +} - packfileReader := packfile.NewStream(reader) - d := packfile.NewDecoder(packfileReader) +func (s *RemoteSuite) TestFetchInvalidBranch(c *C) { + r, err := NewRemote(RepositoryFixture) + r.upSrv = &MockGitUploadPackService{} - sto := memory.NewObjectStorage() - err = d.Decode(sto) c.Assert(err, IsNil) - c.Assert(sto.Objects, HasLen, 28) + c.Assert(r.Connect(), IsNil) + + sto := memory.NewObjectStorage() + err = r.Fetch(sto, &FetchOptions{ + ReferenceName: core.ReferenceName("qux"), + }) + + c.Assert(err, NotNil) } -*/ func (s *RemoteSuite) TestHead(c *C) { r, err := NewRemote(RepositoryFixture) r.upSrv = &MockGitUploadPackService{} + c.Assert(err, IsNil) + err = r.Connect() + c.Assert(err, IsNil) + c.Assert(r.Head().Hash(), Equals, core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) +} + +func (s *RemoteSuite) TestRef(c *C) { + r, err := NewRemote(RepositoryFixture) + r.upSrv = &MockGitUploadPackService{} c.Assert(err, IsNil) err = r.Connect() c.Assert(err, IsNil) + ref, err := r.Ref(core.HEAD, false) c.Assert(err, IsNil) - c.Assert(r.Head().Hash(), Equals, core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) + c.Assert(ref.Name(), Equals, core.HEAD) + + ref, err = r.Ref(core.HEAD, true) + c.Assert(err, IsNil) + c.Assert(ref.Name(), Equals, core.ReferenceName("refs/heads/master")) +} + +func (s *RemoteSuite) TestRefs(c *C) { + r, err := NewRemote(RepositoryFixture) + r.upSrv = &MockGitUploadPackService{} + c.Assert(err, IsNil) + + err = r.Connect() + c.Assert(err, IsNil) + c.Assert(r.Refs(), NotNil) } diff --git a/repository.go b/repository.go index 2d57295..f286e03 100644 --- a/repository.go +++ b/repository.go @@ -53,6 +53,8 @@ func NewRepository(s core.Storage) (*Repository, error) { // Clone clones a remote repository func (r *Repository) Clone(o *CloneOptions) error { + o.Default() + remote, err := r.createDefaultRemote(o.URL, o.Auth) if err != nil { return err @@ -62,15 +64,17 @@ func (r *Repository) Clone(o *CloneOptions) error { return err } - h, err := remote.Fetch(r.os, &FetchOptions{ - ReferenceName: core.HEAD, - }) + err = remote.Fetch(r.os, &FetchOptions{ReferenceName: o.ReferenceName}) + if err != nil { + return err + } + ref, err := remote.Ref(o.ReferenceName, true) if err != nil { return err } - return r.rs.Set(core.NewHashReference(core.HEAD, h)) + return r.createDefaultBranch(ref) } func (r *Repository) createDefaultRemote(url string, auth common.AuthMethod) (*Remote, error) { @@ -86,6 +90,19 @@ func (r *Repository) createDefaultRemote(url string, auth common.AuthMethod) (*R return remote, nil } +func (r *Repository) createDefaultBranch(ref *core.Reference) error { + if !ref.IsBranch() { + // detached HEAD mode + return r.rs.Set(core.NewHashReference(core.HEAD, ref.Hash())) + } + + if err := r.rs.Set(ref); err != nil { + return err + } + + return r.rs.Set(core.NewSymbolicReference(core.HEAD, ref.Name())) +} + // Commit return the commit with the given hash func (r *Repository) Commit(h core.Hash) (*Commit, error) { obj, err := r.os.Get(h) @@ -191,12 +208,22 @@ func (r *Repository) Object(h core.Hash) (Object, error) { } } -// Head returns the hash of the HEAD of the repository or the head of a -// remote, if one is passed. -func (r *Repository) Head(resolved bool) (*core.Reference, error) { +// Head returns the reference where HEAD is pointing +func (r *Repository) Head() (*core.Reference, error) { + return core.ResolveReference(r.rs, core.HEAD) +} + +// Ref returns the Hash pointing the given refName +func (r *Repository) Ref(name core.ReferenceName, resolved bool) (*core.Reference, error) { if resolved { - return core.ResolveReference(r.rs, core.HEAD) + return core.ResolveReference(r.rs, name) } - return r.rs.Get(core.HEAD) + return r.rs.Get(name) +} + +// Refs returns a map with all the References +func (r *Repository) Refs() core.ReferenceIter { + i, _ := r.rs.Iter() + return i } diff --git a/repository_test.go b/repository_test.go index 3ca4d0d..80bd0d1 100644 --- a/repository_test.go +++ b/repository_test.go @@ -60,58 +60,68 @@ func (s *RepositorySuite) TearDownSuite(c *C) { } } -/* func (s *RepositorySuite) TestNewRepository(c *C) { - r, err := NewRepository(RepositoryFixture, nil) + r, err := NewMemoryRepository() c.Assert(err, IsNil) - c.Assert(r.Remotes["origin"].Auth, IsNil) + c.Assert(r, NotNil) } -func (s *RepositorySuite) TestNewRepositoryWithAuth(c *C) { - auth := &http.BasicAuth{} - r, err := NewRepository(RepositoryFixture, auth) +func (s *RepositorySuite) TestClone(c *C) { + r, err := NewMemoryRepository() c.Assert(err, IsNil) - c.Assert(r.Remotes["origin"].Auth, Equals, auth) -} + c.Assert(r.Remotes, HasLen, 0) -func (s *RepositorySuite) TestNewRepositoryFromFS(c *C) { - for name, fix := range s.dirFixtures { - fs := fs.NewOS() - gitPath := fs.Join(fix.path, ".git/") - com := Commentf("dir fixture %q → %q\n", name, gitPath) - repo, err := NewRepositoryFromFS(fs, gitPath) - c.Assert(err, IsNil, com) + head, err := r.Head() + c.Assert(err, Equals, core.ErrReferenceNotFound) + c.Assert(head, IsNil) - err = repo.PullDefault() - c.Assert(err, ErrorMatches, `unable to find remote "origin"`) + err = r.Clone(&CloneOptions{ + URL: RepositoryFixture, + }) - c.Assert(repo.Storage, NotNil, com) - c.Assert(repo.Storage, FitsTypeOf, &filesystem.ObjectStorage{}, com) - } -} + c.Assert(err, IsNil) + c.Assert(r.Remotes, HasLen, 1) + c.Assert(r.Remotes[DefaultRemoteName], NotNil) + head, err = r.Ref(core.HEAD, false) + c.Assert(err, IsNil) + c.Assert(head, NotNil) + c.Assert(head.Type(), Equals, core.SymbolicReference) + c.Assert(head.Target().String(), Equals, "refs/heads/master") -func (s *RepositorySuite) TestClone(c *C) { - r, err := NewRepository(RepositoryFixture, nil) - r.Remotes["origin"].upSrv = &MockGitUploadPackService{} + branch, err := r.Ref(head.Target(), false) + c.Assert(err, IsNil) + c.Assert(branch, NotNil) + c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") +} +func (s *RepositorySuite) TestCloneDetachedHEAD(c *C) { + r, err := NewMemoryRepository() c.Assert(err, IsNil) - c.Assert(r.Pull("origin", "refs/heads/master"), IsNil) - mock, ok := (r.Remotes["origin"].upSrv).(*MockGitUploadPackService) - c.Assert(ok, Equals, true) - err = mock.RC.Close() - c.Assert(err, Not(IsNil), Commentf("pull leaks an open fd from the fetch")) -} + c.Assert(r.Remotes, HasLen, 0) + err = r.Clone(&CloneOptions{ + URL: RepositoryFixture, + ReferenceName: core.ReferenceName("refs/tags/v1.0.0"), + }) + head, err := r.Ref(core.HEAD, false) + c.Assert(err, IsNil) + c.Assert(head, NotNil) + c.Assert(head.Type(), Equals, core.HashReference) + c.Assert(head.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") +} func (s *RepositorySuite) TestCommit(c *C) { - r, err := NewRepository(RepositoryFixture, nil) - r.Remotes["origin"].upSrv = &MockGitUploadPackService{} + r, err := NewMemoryRepository() + c.Assert(err, IsNil) + + err = r.Clone(&CloneOptions{ + URL: RepositoryFixture, + }) c.Assert(err, IsNil) - c.Assert(r.Pull("origin", "refs/heads/master"), IsNil) hash := core.NewHash("b8e471f58bcbca63b07bda20e428190409c2db47") commit, err := r.Commit(hash) @@ -124,7 +134,6 @@ func (s *RepositorySuite) TestCommit(c *C) { c.Assert(commit.Tree().Hash.IsZero(), Equals, false) c.Assert(commit.Author.Email, Equals, "daniel@lordran.local") } -*/ func (s *RepositorySuite) TestCommits(c *C) { r, err := NewMemoryRepository() @@ -192,67 +201,41 @@ func (s *RepositorySuite) TestObject(c *C) { } } -/* func (s *RepositorySuite) TestCommitIterClosePanic(c *C) { - r, err := NewRepository(RepositoryFixture, nil) - r.Remotes["origin"].upSrv = &MockGitUploadPackService{} + r, err := NewMemoryRepository() + c.Assert(err, IsNil) + err = r.Clone(&CloneOptions{URL: RepositoryFixture}) c.Assert(err, IsNil) - c.Assert(r.Pull("origin", "refs/heads/master"), IsNil) commits, err := r.Commits() c.Assert(err, IsNil) commits.Close() } - -func (s *RepositorySuite) TestHeadFromFs(c *C) { - for name, fix := range s.dirFixtures { - fs := fs.NewOS() - gitPath := fs.Join(fix.path, ".git/") - com := Commentf("dir fixture %q → %q\n", name, gitPath) - repo, err := NewRepositoryFromFS(fs, gitPath) - c.Assert(err, IsNil, com) - - head, err := repo.Head("") - c.Assert(err, IsNil) - - c.Assert(head, Equals, fix.head) - } -} - -func (s *RepositorySuite) TestHeadFromRemote(c *C) { - r, err := NewRepository(RepositoryFixture, nil) +func (s *RepositorySuite) TestRef(c *C) { + r, err := NewMemoryRepository() c.Assert(err, IsNil) - upSrv := &MockGitUploadPackService{} - r.Remotes[DefaultRemoteName].upSrv = upSrv - err = r.Remotes[DefaultRemoteName].Connect() + err = r.Clone(&CloneOptions{URL: RepositoryFixture}) c.Assert(err, IsNil) - info, err := upSrv.Info() + ref, err := r.Ref(core.HEAD, false) c.Assert(err, IsNil) - expected := info.Head + c.Assert(ref.Name(), Equals, core.HEAD) - obtained, err := r.Head(DefaultRemoteName) + ref, err = r.Ref(core.HEAD, true) c.Assert(err, IsNil) - - c.Assert(obtained, Equals, expected) + c.Assert(ref.Name(), Equals, core.ReferenceName("refs/heads/master")) } -func (s *RepositorySuite) TestHeadErrors(c *C) { - r, err := NewRepository(RepositoryFixture, nil) +func (s *RepositorySuite) TestRefs(c *C) { + r, err := NewMemoryRepository() c.Assert(err, IsNil) - upSrv := &MockGitUploadPackService{} - r.Remotes[DefaultRemoteName].upSrv = upSrv - - remote := "not found" - _, err = r.Head(remote) - c.Assert(err, ErrorMatches, fmt.Sprintf("unable to find remote %q", remote)) + err = r.Clone(&CloneOptions{URL: RepositoryFixture}) + c.Assert(err, IsNil) - remote = "" - _, err = r.Head(remote) - c.Assert(err, ErrorMatches, "cannot retrieve local head: no local data found") + c.Assert(err, IsNil) + c.Assert(r.Refs(), NotNil) } -*/ |