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

Commit ced875a

Browse files
authored
Merge pull request #375 from mcuadros/commit
worktree: Commit method implementation
2 parents e80cdba + 3713157 commit ced875a

13 files changed

+559
-54
lines changed

options.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"gopkg.in/src-d/go-git.v4/config"
77
"gopkg.in/src-d/go-git.v4/plumbing"
8+
"gopkg.in/src-d/go-git.v4/plumbing/object"
89
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband"
910
"gopkg.in/src-d/go-git.v4/plumbing/transport"
1011
)
@@ -72,7 +73,7 @@ func (o *CloneOptions) Validate() error {
7273
type PullOptions struct {
7374
// Name of the remote to be pulled. If empty, uses the default.
7475
RemoteName string
75-
// Remote branch to clone. If empty, uses HEAD.
76+
// Remote branch to clone. If empty, uses HEAD.
7677
ReferenceName plumbing.ReferenceName
7778
// Fetch only ReferenceName if true.
7879
SingleBranch bool
@@ -251,3 +252,46 @@ type LogOptions struct {
251252
// the default From.
252253
From plumbing.Hash
253254
}
255+
256+
var (
257+
ErrMissingAuthor = errors.New("author field is required")
258+
)
259+
260+
// CommitOptions describes how a commit operation should be performed.
261+
type CommitOptions struct {
262+
// All automatically stage files that have been modified and deleted, but
263+
// new files you have not told Git about are not affected.
264+
All bool
265+
// Author is the author's signature of the commit.
266+
Author *object.Signature
267+
// Committer is the committer's signature of the commit. If Committer is
268+
// nil the Author signature is used.
269+
Committer *object.Signature
270+
// Parents are the parents commits for the new commit, by default when
271+
// len(Parents) is zero, the hash of HEAD reference is used.
272+
Parents []plumbing.Hash
273+
}
274+
275+
// Validate validates the fields and sets the default values.
276+
func (o *CommitOptions) Validate(r *Repository) error {
277+
if o.Author == nil {
278+
return ErrMissingAuthor
279+
}
280+
281+
if o.Committer == nil {
282+
o.Committer = o.Author
283+
}
284+
285+
if len(o.Parents) == 0 {
286+
head, err := r.Head()
287+
if err != nil && err != plumbing.ErrReferenceNotFound {
288+
return err
289+
}
290+
291+
if head != nil {
292+
o.Parents = []plumbing.Hash{head.Hash()}
293+
}
294+
}
295+
296+
return nil
297+
}

options_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package git
2+
3+
import (
4+
. "gopkg.in/check.v1"
5+
"gopkg.in/src-d/go-git.v4/plumbing/object"
6+
)
7+
8+
type OptionsSuite struct {
9+
BaseSuite
10+
}
11+
12+
var _ = Suite(&OptionsSuite{})
13+
14+
func (s *OptionsSuite) TestCommitOptionsParentsFromHEAD(c *C) {
15+
o := CommitOptions{Author: &object.Signature{}}
16+
err := o.Validate(s.Repository)
17+
c.Assert(err, IsNil)
18+
c.Assert(o.Parents, HasLen, 1)
19+
}
20+
21+
func (s *OptionsSuite) TestCommitOptionsMissingAuthor(c *C) {
22+
o := CommitOptions{}
23+
err := o.Validate(s.Repository)
24+
c.Assert(err, Equals, ErrMissingAuthor)
25+
}
26+
27+
func (s *OptionsSuite) TestCommitOptionsCommitter(c *C) {
28+
sig := &object.Signature{}
29+
30+
o := CommitOptions{Author: sig}
31+
err := o.Validate(s.Repository)
32+
c.Assert(err, IsNil)
33+
34+
c.Assert(o.Committer, Equals, o.Author)
35+
}

plumbing/memory.go

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ func (o *MemoryObject) Writer() (io.WriteCloser, error) {
5151

5252
func (o *MemoryObject) Write(p []byte) (n int, err error) {
5353
o.cont = append(o.cont, p...)
54+
o.sz = int64(len(o.cont))
55+
5456
return len(p), nil
5557
}
5658

plumbing/object/blob.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,23 @@ func (b *Blob) Decode(o plumbing.EncodedObject) error {
6868

6969
// Encode transforms a Blob into a plumbing.EncodedObject.
7070
func (b *Blob) Encode(o plumbing.EncodedObject) error {
71+
o.SetType(plumbing.BlobObject)
72+
7173
w, err := o.Writer()
7274
if err != nil {
7375
return err
7476
}
77+
7578
defer ioutil.CheckClose(w, &err)
79+
7680
r, err := b.Reader()
7781
if err != nil {
7882
return err
7983
}
84+
8085
defer ioutil.CheckClose(r, &err)
86+
8187
_, err = io.Copy(w, r)
82-
o.SetType(plumbing.BlobObject)
8388
return err
8489
}
8590

plumbing/object/commit.go

+21-10
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ type Commit struct {
3030
Committer Signature
3131
// Message is the commit message, contains arbitrary text.
3232
Message string
33+
// TreeHash is the hash of the root tree of the commit.
34+
TreeHash plumbing.Hash
35+
// ParentHashes are the hashes of the parent commits of the commit.
36+
ParentHashes []plumbing.Hash
3337

34-
tree plumbing.Hash
35-
parents []plumbing.Hash
36-
s storer.EncodedObjectStorer
38+
s storer.EncodedObjectStorer
3739
}
3840

3941
// GetCommit gets a commit from an object storer and decodes it.
@@ -59,19 +61,19 @@ func DecodeCommit(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Comm
5961

6062
// Tree returns the Tree from the commit.
6163
func (c *Commit) Tree() (*Tree, error) {
62-
return GetTree(c.s, c.tree)
64+
return GetTree(c.s, c.TreeHash)
6365
}
6466

6567
// Parents return a CommitIter to the parent Commits.
6668
func (c *Commit) Parents() CommitIter {
6769
return NewCommitIter(c.s,
68-
storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, c.parents),
70+
storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, c.ParentHashes),
6971
)
7072
}
7173

7274
// NumParents returns the number of parents in a commit.
7375
func (c *Commit) NumParents() int {
74-
return len(c.parents)
76+
return len(c.ParentHashes)
7577
}
7678

7779
// File returns the file with the specified "path" in the commit and a
@@ -144,9 +146,9 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
144146
split := bytes.SplitN(line, []byte{' '}, 2)
145147
switch string(split[0]) {
146148
case "tree":
147-
c.tree = plumbing.NewHash(string(split[1]))
149+
c.TreeHash = plumbing.NewHash(string(split[1]))
148150
case "parent":
149-
c.parents = append(c.parents, plumbing.NewHash(string(split[1])))
151+
c.ParentHashes = append(c.ParentHashes, plumbing.NewHash(string(split[1])))
150152
case "author":
151153
c.Author.Decode(split[1])
152154
case "committer":
@@ -169,30 +171,39 @@ func (b *Commit) Encode(o plumbing.EncodedObject) error {
169171
if err != nil {
170172
return err
171173
}
174+
172175
defer ioutil.CheckClose(w, &err)
173-
if _, err = fmt.Fprintf(w, "tree %s\n", b.tree.String()); err != nil {
176+
177+
if _, err = fmt.Fprintf(w, "tree %s\n", b.TreeHash.String()); err != nil {
174178
return err
175179
}
176-
for _, parent := range b.parents {
180+
181+
for _, parent := range b.ParentHashes {
177182
if _, err = fmt.Fprintf(w, "parent %s\n", parent.String()); err != nil {
178183
return err
179184
}
180185
}
186+
181187
if _, err = fmt.Fprint(w, "author "); err != nil {
182188
return err
183189
}
190+
184191
if err = b.Author.Encode(w); err != nil {
185192
return err
186193
}
194+
187195
if _, err = fmt.Fprint(w, "\ncommitter "); err != nil {
188196
return err
189197
}
198+
190199
if err = b.Committer.Encode(w); err != nil {
191200
return err
192201
}
202+
193203
if _, err = fmt.Fprintf(w, "\n\n%s", b.Message); err != nil {
194204
return err
195205
}
206+
196207
return err
197208
}
198209

plumbing/object/commit_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,18 @@ func (s *SuiteCommit) TestCommitEncodeDecodeIdempotent(c *C) {
7171
c.Assert(err, IsNil)
7272
commits := []*Commit{
7373
{
74-
Author: Signature{Name: "Foo", Email: "[email protected]", When: ts},
75-
Committer: Signature{Name: "Bar", Email: "[email protected]", When: ts},
76-
Message: "Message\n\nFoo\nBar\nWith trailing blank lines\n\n",
77-
tree: plumbing.NewHash("f000000000000000000000000000000000000001"),
78-
parents: []plumbing.Hash{plumbing.NewHash("f000000000000000000000000000000000000002")},
74+
Author: Signature{Name: "Foo", Email: "[email protected]", When: ts},
75+
Committer: Signature{Name: "Bar", Email: "[email protected]", When: ts},
76+
Message: "Message\n\nFoo\nBar\nWith trailing blank lines\n\n",
77+
TreeHash: plumbing.NewHash("f000000000000000000000000000000000000001"),
78+
ParentHashes: []plumbing.Hash{plumbing.NewHash("f000000000000000000000000000000000000002")},
7979
},
8080
{
8181
Author: Signature{Name: "Foo", Email: "[email protected]", When: ts},
8282
Committer: Signature{Name: "Bar", Email: "[email protected]", When: ts},
8383
Message: "Message\n\nFoo\nBar\nWith no trailing blank lines",
84-
tree: plumbing.NewHash("0000000000000000000000000000000000000003"),
85-
parents: []plumbing.Hash{
84+
TreeHash: plumbing.NewHash("0000000000000000000000000000000000000003"),
85+
ParentHashes: []plumbing.Hash{
8686
plumbing.NewHash("f000000000000000000000000000000000000004"),
8787
plumbing.NewHash("f000000000000000000000000000000000000005"),
8888
plumbing.NewHash("f000000000000000000000000000000000000006"),

plumbing/object/tag_test.go

+17-18
Original file line numberDiff line numberDiff line change
@@ -234,41 +234,40 @@ func (s *TagSuite) TestString(c *C) {
234234
)
235235
}
236236

237-
func (s *TagSuite) TestTagToTagString(c *C) {
237+
func (s *TagSuite) TestStringNonCommit(c *C) {
238238
store := memory.NewStorage()
239239

240-
tagOneHash := plumbing.NewHash("TAGONE")
241-
tagTwoHash := plumbing.NewHash("TAGTWO")
242-
243-
tagOne := &Tag{
244-
Target: tagTwoHash,
245-
Hash: tagOneHash,
240+
target := &Tag{
241+
Target: plumbing.NewHash("TAGONE"),
246242
Name: "TAG ONE",
243+
Message: "tag one",
247244
TargetType: plumbing.TagObject,
248245
}
249-
tagTwo := &Tag{
250-
Target: tagOneHash,
251-
Hash: tagTwoHash,
246+
247+
targetObj := &plumbing.MemoryObject{}
248+
target.Encode(targetObj)
249+
store.SetEncodedObject(targetObj)
250+
251+
tag := &Tag{
252+
Target: targetObj.Hash(),
252253
Name: "TAG TWO",
254+
Message: "tag two",
253255
TargetType: plumbing.TagObject,
254256
}
255-
oOne := &plumbing.MemoryObject{}
256-
tagOne.Encode(oOne)
257-
oTwo := &plumbing.MemoryObject{}
258-
tagTwo.Encode(oTwo)
259257

260-
store.SetEncodedObject(oOne)
261-
store.SetEncodedObject(oTwo)
258+
tagObj := &plumbing.MemoryObject{}
259+
tag.Encode(tagObj)
260+
store.SetEncodedObject(tagObj)
262261

263-
tag, err := GetTag(store, tagOneHash)
262+
tag, err := GetTag(store, tagObj.Hash())
264263
c.Assert(err, IsNil)
265264

266265
c.Assert(tag.String(), Equals,
267266
"tag TAG TWO\n"+
268267
"Tagger: <>\n"+
269268
"Date: Mon Jan 01 00:00:00 0001 +0000\n"+
270269
"\n"+
271-
"\n")
270+
"tag two\n")
272271
}
273272

274273
func (s *TagSuite) TestLongTagNameSerialization(c *C) {

plumbing/object/tree.go

+3-11
Original file line numberDiff line numberDiff line change
@@ -240,29 +240,21 @@ func (t *Tree) Encode(o plumbing.EncodedObject) error {
240240
return err
241241
}
242242

243-
var size int
244243
defer ioutil.CheckClose(w, &err)
245244
for _, entry := range t.Entries {
246-
n, err := fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name)
247-
if err != nil {
245+
if _, err := fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil {
248246
return err
249247
}
250248

251-
size += n
252-
n, err = w.Write([]byte{0x00})
253-
if err != nil {
249+
if _, err = w.Write([]byte{0x00}); err != nil {
254250
return err
255251
}
256252

257-
size += n
258-
n, err = w.Write([]byte(entry.Hash[:]))
259-
if err != nil {
253+
if _, err = w.Write([]byte(entry.Hash[:])); err != nil {
260254
return err
261255
}
262-
size += n
263256
}
264257

265-
o.SetSize(int64(size))
266258
return err
267259
}
268260

status.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ type Status map[string]*FileStatus
1111
// exists a new FileStatus is added to the map using the path as key.
1212
func (s Status) File(path string) *FileStatus {
1313
if _, ok := (s)[path]; !ok {
14-
s[path] = &FileStatus{Worktree: Unmodified, Staging: Unmodified}
14+
s[path] = &FileStatus{Worktree: Untracked, Staging: Untracked}
1515
}
1616

1717
return s[path]

0 commit comments

Comments
 (0)