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

Commit f1a0578

Browse files
smolamcuadros
authored andcommitted
storage/filesystem: implement missing functionality. (#110)
* storage/filesystem: added ObjectStorage Set. * storage/filesystem: now passes all tests, except those specific to transactions. * formats/config: Encoder now encodes subsections with no options. * formats/config: add HasSubsection on Section. * dotgit: add Ref method to get specific reference.
1 parent f0b4324 commit f1a0578

File tree

11 files changed

+241
-94
lines changed

11 files changed

+241
-94
lines changed

formats/config/common_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type CommonSuite struct{}
1313
var _ = Suite(&CommonSuite{})
1414

1515
func (s *CommonSuite) TestConfig_SetOption(c *C) {
16-
obtained := New().SetOption("section", "", "key1", "value1")
16+
obtained := New().SetOption("section", NoSubsection, "key1", "value1")
1717
expected := &Config{
1818
Sections: []*Section{
1919
{
@@ -25,7 +25,7 @@ func (s *CommonSuite) TestConfig_SetOption(c *C) {
2525
},
2626
}
2727
c.Assert(obtained, DeepEquals, expected)
28-
obtained = obtained.SetOption("section", "", "key1", "value1")
28+
obtained = obtained.SetOption("section", NoSubsection, "key1", "value1")
2929
c.Assert(obtained, DeepEquals, expected)
3030

3131
obtained = New().SetOption("section", "subsection", "key1", "value1")
@@ -50,7 +50,7 @@ func (s *CommonSuite) TestConfig_SetOption(c *C) {
5050
}
5151

5252
func (s *CommonSuite) TestConfig_AddOption(c *C) {
53-
obtained := New().AddOption("section", "", "key1", "value1")
53+
obtained := New().AddOption("section", NoSubsection, "key1", "value1")
5454
expected := &Config{
5555
Sections: []*Section{
5656
{
@@ -66,10 +66,10 @@ func (s *CommonSuite) TestConfig_AddOption(c *C) {
6666

6767
func (s *CommonSuite) TestConfig_RemoveSection(c *C) {
6868
sect := New().
69-
AddOption("section1", "", "key1", "value1").
70-
AddOption("section2", "", "key1", "value1")
69+
AddOption("section1", NoSubsection, "key1", "value1").
70+
AddOption("section2", NoSubsection, "key1", "value1")
7171
expected := New().
72-
AddOption("section1", "", "key1", "value1")
72+
AddOption("section1", NoSubsection, "key1", "value1")
7373
c.Assert(sect.RemoveSection("other"), DeepEquals, sect)
7474
c.Assert(sect.RemoveSection("section2"), DeepEquals, expected)
7575
}

formats/config/encoder.go

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
// An Encoder writes config files to an output stream.
99
type Encoder struct {
10-
io.Writer
10+
w io.Writer
1111
}
1212

1313
// NewEncoder returns a new encoder that writes to w.
@@ -18,21 +18,58 @@ func NewEncoder(w io.Writer) *Encoder {
1818
// Encode writes the config in git config format to the stream of the encoder.
1919
func (e *Encoder) Encode(cfg *Config) error {
2020
for _, s := range cfg.Sections {
21-
if len(s.Options) > 0 {
22-
fmt.Fprintf(e, "[%s]\n", s.Name)
23-
for _, o := range s.Options {
24-
fmt.Fprintf(e, "\t%s = %s\n", o.Key, o.Value)
25-
}
21+
if err := e.encodeSection(s); err != nil {
22+
return err
2623
}
27-
for _, ss := range s.Subsections {
28-
if len(ss.Options) > 0 {
29-
//TODO: escape
30-
fmt.Fprintf(e, "[%s \"%s\"]\n", s.Name, ss.Name)
31-
for _, o := range ss.Options {
32-
fmt.Fprintf(e, "\t%s = %s\n", o.Key, o.Value)
33-
}
34-
}
24+
}
25+
26+
return nil
27+
}
28+
29+
func (e *Encoder) encodeSection(s *Section) error {
30+
if len(s.Options) > 0 {
31+
if err := e.printf("[%s]\n", s.Name); err != nil {
32+
return err
33+
}
34+
35+
if err := e.encodeOptions(s.Options); err != nil {
36+
return err
37+
}
38+
}
39+
40+
for _, ss := range s.Subsections {
41+
if err := e.encodeSubsection(s.Name, ss); err != nil {
42+
return err
43+
}
44+
}
45+
46+
return nil
47+
}
48+
49+
func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error {
50+
//TODO: escape
51+
if err := e.printf("[%s \"%s\"]\n", sectionName, s.Name); err != nil {
52+
return err
53+
}
54+
55+
if err := e.encodeOptions(s.Options); err != nil {
56+
return err
57+
}
58+
59+
return nil
60+
}
61+
62+
func (e *Encoder) encodeOptions(opts Options) error {
63+
for _, o := range opts {
64+
if err := e.printf("\t%s = %s\n", o.Key, o.Value); err != nil {
65+
return err
3566
}
3667
}
68+
3769
return nil
3870
}
71+
72+
func (e *Encoder) printf(msg string, args ...interface{}) error {
73+
_, err := fmt.Fprintf(e.w, msg, args...)
74+
return err
75+
}

formats/config/section.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,13 @@ func (s *Section) Subsection(name string) *Subsection {
7474
s.Subsections = append(s.Subsections, ss)
7575
return ss
7676
}
77+
78+
func (s *Section) HasSubsection(name string) bool {
79+
for _, ss := range s.Subsections {
80+
if ss.IsName(name) {
81+
return true
82+
}
83+
}
84+
85+
return false
86+
}

storage/filesystem/config.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ func (c *ConfigStorage) Remote(name string) (*config.RemoteConfig, error) {
2424
return nil, err
2525
}
2626

27-
s := cfg.Section(remoteSection).Subsection(name)
28-
if s == nil {
27+
s := cfg.Section(remoteSection)
28+
if !s.HasSubsection(name) {
2929
return nil, config.ErrRemoteConfigNotFound
3030
}
3131

32-
return parseRemote(s), nil
32+
return parseRemote(s.Subsection(name)), nil
3333
}
3434

3535
func (c *ConfigStorage) Remotes() ([]*config.RemoteConfig, error) {
@@ -48,14 +48,20 @@ func (c *ConfigStorage) Remotes() ([]*config.RemoteConfig, error) {
4848
}
4949

5050
func (c *ConfigStorage) SetRemote(r *config.RemoteConfig) error {
51+
if err := r.Validate(); err != nil {
52+
return err
53+
}
54+
5155
cfg, err := c.read()
5256
if err != nil {
5357
return err
5458
}
5559

5660
s := cfg.Section(remoteSection).Subsection(r.Name)
5761
s.Name = r.Name
58-
s.SetOption(urlKey, r.URL)
62+
if r.URL != "" {
63+
s.SetOption(urlKey, r.URL)
64+
}
5965
s.RemoveOption(fetchKey)
6066
for _, rs := range r.Fetch {
6167
s.AddOption(fetchKey, rs.String())
@@ -103,15 +109,14 @@ func (c *ConfigStorage) write(cfg *gitconfig.Config) error {
103109
return err
104110
}
105111

106-
defer f.Close()
107-
108112
e := gitconfig.NewEncoder(f)
109113
err = e.Encode(cfg)
110114
if err != nil {
115+
f.Close()
111116
return err
112117
}
113118

114-
return nil
119+
return f.Close()
115120
}
116121

117122
func parseRemote(s *gitconfig.Subsection) *config.RemoteConfig {

storage/filesystem/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (s *ConfigSuite) SetUpTest(c *C) {
3131

3232
func (s *ConfigSuite) TestSetRemote(c *C) {
3333
cfg := &ConfigStorage{s.dir}
34-
err := cfg.SetRemote(&config.RemoteConfig{Name: "foo"})
34+
err := cfg.SetRemote(&config.RemoteConfig{Name: "foo", URL: "foo"})
3535
c.Assert(err, IsNil)
3636

3737
remote, err := cfg.Remote("foo")

storage/filesystem/internal/dotgit/dotgit.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,27 @@ func (d *DotGit) Refs() ([]*core.Reference, error) {
215215
return refs, nil
216216
}
217217

218+
// Ref returns the reference for a given reference name.
219+
func (d *DotGit) Ref(name core.ReferenceName) (*core.Reference, error) {
220+
ref, err := d.readReferenceFile(".", name.String())
221+
if err == nil {
222+
return ref, nil
223+
}
224+
225+
refs, err := d.Refs()
226+
if err != nil {
227+
return nil, err
228+
}
229+
230+
for _, ref := range refs {
231+
if ref.Name() == name {
232+
return ref, nil
233+
}
234+
}
235+
236+
return nil, core.ErrReferenceNotFound
237+
}
238+
218239
func (d *DotGit) addRefsFromPackedRefs(refs *[]*core.Reference) (err error) {
219240
f, err := d.fs.Open(packedRefsPath)
220241
if err != nil {

storage/filesystem/internal/dotgit/dotgit_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ func (s *SuiteDotGit) TestSetRefs(c *C) {
4444

4545
c.Assert(err, IsNil)
4646

47+
err = dir.SetRef(core.NewReferenceFromStrings(
48+
"bar",
49+
"e8d3ffab552895c19b9fcf7aa264d277cde33881",
50+
))
51+
c.Assert(err, IsNil)
52+
4753
refs, err := dir.Refs()
4854
c.Assert(err, IsNil)
4955
c.Assert(refs, HasLen, 2)
@@ -55,6 +61,25 @@ func (s *SuiteDotGit) TestSetRefs(c *C) {
5561
ref = findReference(refs, "refs/heads/symbolic")
5662
c.Assert(ref, NotNil)
5763
c.Assert(ref.Target().String(), Equals, "refs/heads/foo")
64+
65+
ref = findReference(refs, "bar")
66+
c.Assert(ref, IsNil)
67+
68+
ref, err = dir.Ref("refs/heads/foo")
69+
c.Assert(err, IsNil)
70+
c.Assert(ref, NotNil)
71+
c.Assert(ref.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
72+
73+
ref, err = dir.Ref("refs/heads/symbolic")
74+
c.Assert(err, IsNil)
75+
c.Assert(ref, NotNil)
76+
c.Assert(ref.Target().String(), Equals, "refs/heads/foo")
77+
78+
ref, err = dir.Ref("bar")
79+
c.Assert(err, IsNil)
80+
c.Assert(ref, NotNil)
81+
c.Assert(ref.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881")
82+
5883
}
5984

6085
func (s *SuiteDotGit) TestRefsFromPackedRefs(c *C) {

storage/filesystem/object.go

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package filesystem
22

33
import (
4-
"fmt"
54
"io"
65
"os"
76

@@ -82,11 +81,35 @@ func (s *ObjectStorage) Writer() (io.WriteCloser, error) {
8281
return w, nil
8382
}
8483

85-
// Set adds a new object to the storage. As this functionality is not
86-
// yet supported, this method always returns a "not implemented yet"
87-
// error an zero hash.
88-
func (s *ObjectStorage) Set(core.Object) (core.Hash, error) {
89-
return core.ZeroHash, fmt.Errorf("set - not implemented yet")
84+
// Set adds a new object to the storage.
85+
func (s *ObjectStorage) Set(o core.Object) (core.Hash, error) {
86+
if o.Type() == core.OFSDeltaObject || o.Type() == core.REFDeltaObject {
87+
return core.ZeroHash, core.ErrInvalidType
88+
}
89+
90+
ow, err := s.dir.NewObject()
91+
if err != nil {
92+
return core.ZeroHash, err
93+
}
94+
95+
defer ow.Close()
96+
97+
or, err := o.Reader()
98+
if err != nil {
99+
return core.ZeroHash, err
100+
}
101+
102+
defer or.Close()
103+
104+
if err := ow.WriteHeader(o.Type(), o.Size()); err != nil {
105+
return core.ZeroHash, err
106+
}
107+
108+
if _, err := io.Copy(ow, or); err != nil {
109+
return core.ZeroHash, err
110+
}
111+
112+
return o.Hash(), nil
90113
}
91114

92115
// Get returns the object with the given hash, by searching for it in
@@ -228,26 +251,18 @@ func (s *ObjectStorage) buildPackfileIters(
228251
return iters, nil
229252
}
230253

254+
// Begin opens a new transaction. However, this implementation is not
255+
// transactional, so Commit and Rollback have no effect.
231256
func (o *ObjectStorage) Begin() core.TxObjectStorage {
232-
return &TxObjectStorage{}
233-
}
234-
235-
type TxObjectStorage struct{}
236-
237-
func (tx *TxObjectStorage) Set(obj core.Object) (core.Hash, error) {
238-
return core.ZeroHash, fmt.Errorf("tx.Set - not implemented yet")
239-
}
240-
241-
func (tx *TxObjectStorage) Get(core.ObjectType, core.Hash) (core.Object, error) {
242-
return nil, fmt.Errorf("tx.Get - not implemented yet")
257+
return o
243258
}
244259

245-
func (tx *TxObjectStorage) Commit() error {
246-
return fmt.Errorf("tx.Commit - not implemented yet")
260+
func (tx *ObjectStorage) Commit() error {
261+
return nil
247262
}
248263

249-
func (tx *TxObjectStorage) Rollback() error {
250-
return fmt.Errorf("tx.Rollback - not implemented yet")
264+
func (tx *ObjectStorage) Rollback() error {
265+
return nil
251266
}
252267

253268
type index map[core.Hash]int64

0 commit comments

Comments
 (0)