Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 2 additions & 2 deletions clients/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func (i *GitUploadPackInfo) addRefs(ar *advrefs.AdvRefs) error {
i.Refs = make(memory.ReferenceStorage, 0)
for name, hash := range ar.References {
ref := core.NewReferenceFromStrings(name, hash.String())
i.Refs.Set(ref)
i.Refs.SetReference(ref)
}

return i.addSymbolicRefs(ar)
Expand All @@ -130,7 +130,7 @@ func (i *GitUploadPackInfo) addSymbolicRefs(ar *advrefs.AdvRefs) error {
name := core.ReferenceName(chunks[0])
target := core.ReferenceName(chunks[1])
ref := core.NewSymbolicReference(name, target)
i.Refs.Set(ref)
i.Refs.SetReference(ref)
}

return nil
Expand Down
8 changes: 3 additions & 5 deletions commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ func (c *Commit) Tree() (*Tree, error) {

// Parents return a CommitIter to the parent Commits
func (c *Commit) Parents() *CommitIter {
return NewCommitIter(c.r, core.NewObjectLookupIter(
c.r.s.ObjectStorage(),
core.CommitObject,
c.parents,
))
return NewCommitIter(c.r,
core.NewObjectLookupIter(c.r.s, core.CommitObject, c.parents),
)
}

// NumParents returns the number of parents in a commit.
Expand Down
2 changes: 1 addition & 1 deletion commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (s *SuiteCommit) SetUpSuite(c *C) {

func (s *SuiteCommit) TestDecodeNonCommit(c *C) {
hash := core.NewHash("9a48f23120e880dfbe41f7c9b7b708e9ee62a492")
blob, err := s.Repository.s.ObjectStorage().Get(core.AnyObject, hash)
blob, err := s.Repository.s.GetObject(core.AnyObject, hash)
c.Assert(err, IsNil)

commit := &Commit{}
Expand Down
11 changes: 6 additions & 5 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import (
"gopkg.in/src-d/go-git.v4/core"
)

// Storage storage of objects and references
type Storage interface {
ConfigStorage() config.ConfigStorage
ObjectStorage() core.ObjectStorage
ReferenceStorage() core.ReferenceStorage
// Storer storage of objects, references and all the information that require
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence makes no sense, it has no verb.

Also, is this comment accurate?, does the memory implementation persist data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// be persisted
type Storer interface {
core.ObjectStorer
core.ReferenceStorer
config.ConfigStorer
}

// countLines returns the number of lines in a string à la git, this is
Expand Down
4 changes: 2 additions & 2 deletions common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s *BaseSuite) buildRepositories(c *C, f fixtures.Fixtures) {
defer f.Close()

n := packfile.NewScanner(f)
d, err := packfile.NewDecoder(n, r.s.ObjectStorage())
d, err := packfile.NewDecoder(n, r.s)
c.Assert(err, IsNil)
_, err = d.Decode()
c.Assert(err, IsNil)
Expand Down Expand Up @@ -155,7 +155,7 @@ func unpackFixtures(c *C, fixtures ...[]packedFixture) map[string]*Repository {
c.Assert(err, IsNil, comment)

r := packfile.NewScanner(f)
d, err := packfile.NewDecoder(r, repos[fixture.url].s.ObjectStorage())
d, err := packfile.NewDecoder(r, repos[fixture.url].s)
c.Assert(err, IsNil, comment)
_, err = d.Decode()
c.Assert(err, IsNil, comment)
Expand Down
39 changes: 34 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,51 @@ import (
)

const (
// DefaultRefSpec is the default refspec used, when none is given
DefaultRefSpec = "+refs/heads/*:refs/remotes/%s/*"
)

// ConfigStorer interface to persist Config objects
type ConfigStorer interface {
Config() (*Config, error)
SetConfig(*Config) error
}

var (
ErrInvalid = errors.New("config invalid remote")
ErrRemoteConfigNotFound = errors.New("remote config not found")
ErrRemoteConfigEmptyURL = errors.New("remote config: empty URL")
ErrRemoteConfigEmptyName = errors.New("remote config: empty name")
)

type ConfigStorage interface {
Remote(name string) (*RemoteConfig, error)
Remotes() ([]*RemoteConfig, error)
SetRemote(*RemoteConfig) error
DeleteRemote(name string) error
// Config contains the repository configuration
type Config struct {
Remotes map[string]*RemoteConfig
}

// NewConfig returns a new empty Config
func NewConfig() *Config {
return &Config{
Remotes: make(map[string]*RemoteConfig, 0),
}
}

// Validate validate the fields and set the default values
func (c *Config) Validate() error {
for name, r := range c.Remotes {
if r.Name != name {
return ErrInvalid
}

if err := r.Validate(); err != nil {
return err
}
}

return nil
}

// RemoteConfig contains the configuration for a given repository
type RemoteConfig struct {
Name string
URL string
Expand Down
20 changes: 20 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ type ConfigSuite struct{}

var _ = Suite(&ConfigSuite{})

func (s *ConfigSuite) TestConfigValidateInvalidRemote(c *C) {
config := &Config{
Remotes: map[string]*RemoteConfig{
"foo": {Name: "foo"},
},
}

c.Assert(config.Validate(), Equals, ErrRemoteConfigEmptyURL)
}

func (s *ConfigSuite) TestConfigValidateInvalidKey(c *C) {
config := &Config{
Remotes: map[string]*RemoteConfig{
"bar": {Name: "foo"},
},
}

c.Assert(config.Validate(), Equals, ErrInvalid)
}

func (s *ConfigSuite) TestRemoteConfigValidateMissingURL(c *C) {
config := &RemoteConfig{Name: "foo"}
c.Assert(config.Validate(), Equals, ErrRemoteConfigEmptyURL)
Expand Down
7 changes: 4 additions & 3 deletions core/memory.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package core
package core

import (
"bytes"
"io"
"io/ioutil"
)

Expand Down Expand Up @@ -39,12 +40,12 @@ func (o *MemoryObject) Size() int64 { return o.sz }
func (o *MemoryObject) SetSize(s int64) { o.sz = s }

// Reader returns a ObjectReader used to read the object's content.
func (o *MemoryObject) Reader() (ObjectReader, error) {
func (o *MemoryObject) Reader() (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewBuffer(o.cont)), nil
}

// Writer returns a ObjectWriter used to write the object's content.
func (o *MemoryObject) Writer() (ObjectWriter, error) {
func (o *MemoryObject) Writer() (io.WriteCloser, error) {
return o, nil
}

Expand Down
25 changes: 5 additions & 20 deletions core/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,15 @@ var (
ErrInvalidType = errors.New("invalid object type")
)

// TODO: Consider adding a Hash function to the ObjectReader and ObjectWriter
// interfaces that returns the hash calculated for the reader or writer.

// ObjectReader is a generic representation of an object reader.
//
// ObjectReader implements io.ReadCloser. Close should be called when finished
// with it.
type ObjectReader io.ReadCloser

// ObjectWriter is a generic representation of an object writer.
//
// ObjectWriter implements io.WriterCloser. Close should be called when finished
// with it.
type ObjectWriter io.WriteCloser

// Object is a generic representation of any git object
type Object interface {
Hash() Hash
Type() ObjectType
SetType(ObjectType)
Size() int64
SetSize(int64)
Reader() (ObjectReader, error)
Writer() (ObjectWriter, error)
Reader() (io.ReadCloser, error)
Writer() (io.WriteCloser, error)
}

// ObjectType internal object type
Expand Down Expand Up @@ -116,15 +101,15 @@ func ParseObjectType(value string) (typ ObjectType, err error) {
// The ObjectLookupIter must be closed with a call to Close() when it is no
// longer needed.
type ObjectLookupIter struct {
storage ObjectStorage
storage ObjectStorer
series []Hash
t ObjectType
pos int
}

// NewObjectLookupIter returns an object iterator given an object storage and
// a slice of object hashes.
func NewObjectLookupIter(storage ObjectStorage, t ObjectType, series []Hash) *ObjectLookupIter {
func NewObjectLookupIter(storage ObjectStorer, t ObjectType, series []Hash) *ObjectLookupIter {
return &ObjectLookupIter{
storage: storage,
series: series,
Expand All @@ -142,7 +127,7 @@ func (iter *ObjectLookupIter) Next() (Object, error) {
}

hash := iter.series[iter.pos]
obj, err := iter.storage.Get(iter.t, hash)
obj, err := iter.storage.GetObject(iter.t, hash)
if err == nil {
iter.pos++
}
Expand Down
8 changes: 4 additions & 4 deletions core/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,18 @@ func (o *MockObjectStorage) NewObject() Object {
return nil
}

func (o *MockObjectStorage) Set(obj Object) (Hash, error) {
func (o *MockObjectStorage) SetObject(obj Object) (Hash, error) {
return ZeroHash, nil
}

func (o *MockObjectStorage) Get(t ObjectType, h Hash) (Object, error) {
func (o *MockObjectStorage) GetObject(t ObjectType, h Hash) (Object, error) {
return &MemoryObject{h: h}, nil
}

func (o *MockObjectStorage) Iter(t ObjectType) (ObjectIter, error) {
func (o *MockObjectStorage) IterObjects(t ObjectType) (ObjectIter, error) {
return nil, nil
}

func (o *MockObjectStorage) Begin() TxObjectStorage {
func (o *MockObjectStorage) Begin() TxObjectStorer {
return nil
}
8 changes: 4 additions & 4 deletions core/reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,15 +203,15 @@ func (iter *ReferenceSliceIter) Close() {
iter.pos = len(iter.series)
}

func ResolveReference(s ReferenceStorage, n ReferenceName) (*Reference, error) {
r, err := s.Get(n)
func ResolveReference(s ReferenceStorer, n ReferenceName) (*Reference, error) {
r, err := s.GetReference(n)
if err != nil || r == nil {
return r, err
}
return resolveReference(s, r, 0)
}

func resolveReference(s ReferenceStorage, r *Reference, recursion int) (*Reference, error) {
func resolveReference(s ReferenceStorer, r *Reference, recursion int) (*Reference, error) {
if r.Type() != SymbolicReference {
return r, nil
}
Expand All @@ -220,7 +220,7 @@ func resolveReference(s ReferenceStorage, r *Reference, recursion int) (*Referen
return nil, ErrMaxResolveRecursion
}

t, err := s.Get(r.Target())
t, err := s.GetReference(r.Target())
if err != nil {
return nil, err
}
Expand Down
69 changes: 37 additions & 32 deletions core/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,46 @@ var (
ErrNotImplemented = errors.New("method not-implemented")
)

// ObjectStorage generic storage of objects
type ObjectStorage interface {
// ObjectStorer generic storage of objects
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the comment to include the word persist, as the other storers.

Copy link
Contributor Author

@mcuadros mcuadros Nov 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as we agreed, persistent is not a property intrinsic to a ObjectStorer

type ObjectStorer interface {
// NewObject returns a new Object, the real type of the object can be a
// custom implementation or the defaul one, MemoryObject
NewObject() Object
// Set save an object into the storage, the object shuld be create with
// the NewObject, method, and file if the type is not supported.
Set(Object) (Hash, error)
// Get an object by hash with the given ObjectType. Implementors should
// return (nil, ErrObjectNotFound) if an object doesn't exist with both the
// given hash and object type.
// SetObject save an object into the storage, the object shuld be create
// with the NewObject, method, and file if the type is not supported.
SetObject(Object) (Hash, error)
// GetObject an object by hash with the given ObjectType. Implementors
// should return (nil, ErrObjectNotFound) if an object doesn't exist with
// both the given hash and object type.
//
// Valid ObjectType values are CommitObject, BlobObject, TagObject,
// TreeObject and AnyObject.
//
// If AnyObject is given, the object must be looked up regardless of its type.
Get(ObjectType, Hash) (Object, error)
// Iter returns a custom ObjectIter over all the object on the storage.
// TreeObject and AnyObject. If AnyObject is given, the object must be
// looked up regardless of its type.
GetObject(ObjectType, Hash) (Object, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be called Object instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

// IterObjects returns a custom ObjectIter over all the object on the
// storage.
//
// Valid ObjectType values are CommitObject, BlobObject, TagObject,
Iter(ObjectType) (ObjectIter, error)
IterObjects(ObjectType) (ObjectIter, error)
}

// ObjectStorerTx is a optional method for ObjectStorer, it enable transaction
// base write and read operations in the storage
type ObjectStorerTx interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are going too far with the naming of this types, I suggest naming this Tx and move it to an store/object package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having another package for a interface maybe is too much. Maybe just call the interface Transactional?

// Begin starts a transaction.
Begin() TxObjectStorage
Begin() TxObjectStorer
}

// ObjectStorageWrite is a optional method for ObjectStorage, it enable direct
// write of packfile to the storage
type ObjectStorageWrite interface {
// Writer retuns a writer for writing a packfile to the Storage, this method
// is optional, if not implemented the ObjectStorage should return a
// ErrNotImplemented error.
// PackfileWriter is a optional method for ObjectStorer, it enable direct write
// of packfile to the storage
type PackfileWriter interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interface and method with the same name: we need to rethink how to organize or code.

// PackfileWriter retuns a writer for writing a packfile to the Storage,
// this method is optional, if not implemented the ObjectStorer should
// return a ErrNotImplemented error.
//
// If the implementation not implements Writer the objects should be written
// using the Set method.
Writer() (io.WriteCloser, error)
PackfileWriter() (io.WriteCloser, error)
}

// ObjectIter is a generic closable interface for iterating over objects.
Expand All @@ -55,20 +60,20 @@ type ObjectIter interface {
Close()
}

// TxObjectStorage is an in-progress storage transaction.
// A transaction must end with a call to Commit or Rollback.
type TxObjectStorage interface {
Set(Object) (Hash, error)
Get(ObjectType, Hash) (Object, error)
// TxObjectStorer is an in-progress storage transaction. A transaction must end
// with a call to Commit or Rollback.
type TxObjectStorer interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have an ObjectStorerTx interface and a TxObjectStorer interface.

We must step back, think and organize the code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also we must split all this concepts in their own files.

SetObject(Object) (Hash, error)
GetObject(ObjectType, Hash) (Object, error)
Commit() error
Rollback() error
}

// ReferenceStorage generic storage of references
type ReferenceStorage interface {
Set(*Reference) error
Get(ReferenceName) (*Reference, error)
Iter() (ReferenceIter, error)
// ReferenceStorer generic storage of references
type ReferenceStorer interface {
SetReference(*Reference) error
GetReference(ReferenceName) (*Reference, error)
IterReferences() (ReferenceIter, error)
}

// ReferenceIter is a generic closable interface for iterating over references
Expand Down
Loading