diff options
-rw-r--r-- | repository.go | 17 | ||||
-rw-r--r-- | repository_test.go | 30 | ||||
-rw-r--r-- | storage/transactional/storage.go | 43 | ||||
-rw-r--r-- | storage/transactional/storage_test.go | 33 |
4 files changed, 114 insertions, 9 deletions
diff --git a/repository.go b/repository.go index de92d64..e5b12b0 100644 --- a/repository.go +++ b/repository.go @@ -49,6 +49,7 @@ var ( ErrRepositoryAlreadyExists = errors.New("repository already exists") ErrRemoteNotFound = errors.New("remote not found") ErrRemoteExists = errors.New("remote already exists") + ErrAnonymousRemoteName = errors.New("anonymous remote name must be 'anonymous'") ErrWorktreeNotProvided = errors.New("worktree should be provided") ErrIsBareRepository = errors.New("worktree not available in a bare repository") ErrUnableToResolveCommit = errors.New("unable to resolve commit") @@ -492,6 +493,22 @@ func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error) { return remote, r.Storer.SetConfig(cfg) } +// CreateRemoteAnonymous creates a new anonymous remote. c.Name must be "anonymous". +// It's used like 'git fetch git@github.com:src-d/go-git.git master:master'. +func (r *Repository) CreateRemoteAnonymous(c *config.RemoteConfig) (*Remote, error) { + if err := c.Validate(); err != nil { + return nil, err + } + + if c.Name != "anonymous" { + return nil, ErrAnonymousRemoteName + } + + remote := newRemote(r.Storer, c) + + return remote, nil +} + // DeleteRemote delete a remote from the repository and delete the config func (r *Repository) DeleteRemote(name string) error { cfg, err := r.Storer.Config() diff --git a/repository_test.go b/repository_test.go index 1549737..ccbe29b 100644 --- a/repository_test.go +++ b/repository_test.go @@ -231,6 +231,36 @@ func (s *RepositorySuite) TestCreateRemoteInvalid(c *C) { c.Assert(remote, IsNil) } +func (s *RepositorySuite) TestCreateRemoteAnonymous(c *C) { + r, _ := Init(memory.NewStorage(), nil) + remote, err := r.CreateRemoteAnonymous(&config.RemoteConfig{ + Name: "anonymous", + URLs: []string{"http://foo/foo.git"}, + }) + + c.Assert(err, IsNil) + c.Assert(remote.Config().Name, Equals, "anonymous") +} + +func (s *RepositorySuite) TestCreateRemoteAnonymousInvalidName(c *C) { + r, _ := Init(memory.NewStorage(), nil) + remote, err := r.CreateRemoteAnonymous(&config.RemoteConfig{ + Name: "not_anonymous", + URLs: []string{"http://foo/foo.git"}, + }) + + c.Assert(err, Equals, ErrAnonymousRemoteName) + c.Assert(remote, IsNil) +} + +func (s *RepositorySuite) TestCreateRemoteAnonymousInvalid(c *C) { + r, _ := Init(memory.NewStorage(), nil) + remote, err := r.CreateRemoteAnonymous(&config.RemoteConfig{}) + + c.Assert(err, Equals, config.ErrRemoteConfigEmptyName) + c.Assert(remote, IsNil) +} + func (s *RepositorySuite) TestDeleteRemote(c *C) { r, _ := Init(memory.NewStorage(), nil) _, err := r.CreateRemote(&config.RemoteConfig{ diff --git a/storage/transactional/storage.go b/storage/transactional/storage.go index fbb3d35..b81b104 100644 --- a/storage/transactional/storage.go +++ b/storage/transactional/storage.go @@ -1,6 +1,9 @@ package transactional import ( + "io" + + "gopkg.in/src-d/go-git.v4/plumbing/storer" "gopkg.in/src-d/go-git.v4/storage" ) @@ -10,7 +13,13 @@ import ( // // The API and functionality of this package are considered EXPERIMENTAL and is // not considered stable nor production ready. -type Storage struct { +type Storage interface { + storage.Storer + Commit() error +} + +// basic implements the Storage interface. +type basic struct { s, temporal storage.Storer *ObjectStorage @@ -20,11 +29,18 @@ type Storage struct { *ConfigStorage } +// packageWriter implements storer.PackfileWriter interface over +// a Storage with a temporal storer that supports it. +type packageWriter struct { + *basic + pw storer.PackfileWriter +} + // NewStorage returns a new Storage based on two repositories, base is the base -// repository where the read operations are read and temportal is were all +// repository where the read operations are read and temporal is were all // the write operations are stored. -func NewStorage(base, temporal storage.Storer) *Storage { - return &Storage{ +func NewStorage(base, temporal storage.Storer) Storage { + st := &basic{ s: base, temporal: temporal, @@ -34,10 +50,20 @@ func NewStorage(base, temporal storage.Storer) *Storage { ShallowStorage: NewShallowStorage(base, temporal), ConfigStorage: NewConfigStorage(base, temporal), } + + pw, ok := temporal.(storer.PackfileWriter) + if ok { + return &packageWriter{ + basic: st, + pw: pw, + } + } + + return st } // Module it honors the storage.ModuleStorer interface. -func (s *Storage) Module(name string) (storage.Storer, error) { +func (s *basic) Module(name string) (storage.Storer, error) { base, err := s.s.Module(name) if err != nil { return nil, err @@ -52,7 +78,7 @@ func (s *Storage) Module(name string) (storage.Storer, error) { } // Commit it copies the content of the temporal storage into the base storage. -func (s *Storage) Commit() error { +func (s *basic) Commit() error { for _, c := range []interface{ Commit() error }{ s.ObjectStorage, s.ReferenceStorage, @@ -67,3 +93,8 @@ func (s *Storage) Commit() error { return nil } + +// PackfileWriter honors storage.PackfileWriter. +func (s *packageWriter) PackfileWriter() (io.WriteCloser, error) { + return s.pw.PackfileWriter() +} diff --git a/storage/transactional/storage_test.go b/storage/transactional/storage_test.go index 6aaea0d..63ebfb1 100644 --- a/storage/transactional/storage_test.go +++ b/storage/transactional/storage_test.go @@ -4,7 +4,12 @@ import ( "testing" . "gopkg.in/check.v1" + "gopkg.in/src-d/go-billy.v4/memfs" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/cache" + "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/storage" + "gopkg.in/src-d/go-git.v4/storage/filesystem" "gopkg.in/src-d/go-git.v4/storage/memory" "gopkg.in/src-d/go-git.v4/storage/test" ) @@ -13,13 +18,25 @@ func Test(t *testing.T) { TestingT(t) } type StorageSuite struct { test.BaseStorageSuite + temporal func() storage.Storer } -var _ = Suite(&StorageSuite{}) +var _ = Suite(&StorageSuite{ + temporal: func() storage.Storer { + return memory.NewStorage() + }, +}) + +var _ = Suite(&StorageSuite{ + temporal: func() storage.Storer { + fs := memfs.New() + return filesystem.NewStorage(fs, cache.NewObjectLRUDefault()) + }, +}) func (s *StorageSuite) SetUpTest(c *C) { base := memory.NewStorage() - temporal := memory.NewStorage() + temporal := s.temporal() s.BaseStorageSuite = test.NewBaseStorageSuite(NewStorage(base, temporal)) s.BaseStorageSuite.SetUpTest(c) @@ -27,7 +44,7 @@ func (s *StorageSuite) SetUpTest(c *C) { func (s *StorageSuite) TestCommit(c *C) { base := memory.NewStorage() - temporal := memory.NewStorage() + temporal := s.temporal() st := NewStorage(base, temporal) commit := base.NewEncodedObject() @@ -50,3 +67,13 @@ func (s *StorageSuite) TestCommit(c *C) { c.Assert(err, IsNil) c.Assert(obj.Hash(), Equals, commit.Hash()) } + +func (s *StorageSuite) TestTransactionalPackfileWriter(c *C) { + base := memory.NewStorage() + temporal := s.temporal() + st := NewStorage(base, temporal) + + _, tmpOK := temporal.(storer.PackfileWriter) + _, ok := st.(storer.PackfileWriter) + c.Assert(ok, Equals, tmpOK) +} |