aboutsummaryrefslogtreecommitdiffstats
path: root/commit.go
diff options
context:
space:
mode:
Diffstat (limited to 'commit.go')
-rw-r--r--commit.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/commit.go b/commit.go
new file mode 100644
index 0000000..b8a2772
--- /dev/null
+++ b/commit.go
@@ -0,0 +1,127 @@
+package git
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+
+ "gopkg.in/src-d/go-git.v2/internal"
+)
+
+// Commit points to a single tree, marking it as what the project looked like
+// at a certain point in time. It contains meta-information about that point
+// in time, such as a timestamp, the author of the changes since the last
+// commit, a pointer to the previous commit(s), etc.
+// http://schacon.github.io/gitbook/1_the_git_object_model.html
+type Commit struct {
+ Hash internal.Hash
+ Author Signature
+ Committer Signature
+ Message string
+
+ tree internal.Hash
+ parents []internal.Hash
+ r *Repository
+}
+
+func (c *Commit) Tree() *Tree {
+ tree, _ := c.r.Tree(c.tree)
+ return tree
+}
+
+func (c *Commit) Parents() *CommitIter {
+ i := NewCommitIter(c.r)
+ go func() {
+ defer i.Close()
+ for _, hash := range c.parents {
+ obj, _ := c.r.Storage.Get(hash)
+ i.Add(obj)
+ }
+ }()
+
+ return i
+}
+
+// Decode transform an internal.Object into a Blob struct
+func (c *Commit) Decode(o internal.Object) error {
+ c.Hash = o.Hash()
+ r := bufio.NewReader(o.Reader())
+
+ var message bool
+ for {
+ line, err := r.ReadSlice('\n')
+ if err != nil && err != io.EOF {
+ return err
+ }
+
+ line = bytes.TrimSpace(line)
+ if !message {
+ if len(line) == 0 {
+ message = true
+ continue
+ }
+
+ split := bytes.SplitN(line, []byte{' '}, 2)
+ switch string(split[0]) {
+ case "tree":
+ c.tree = internal.NewHash(string(split[1]))
+ case "parent":
+ c.parents = append(c.parents, internal.NewHash(string(split[1])))
+ case "author":
+ c.Author.Decode(split[1])
+ case "committer":
+ c.Committer.Decode(split[1])
+ }
+ } else {
+ c.Message += string(line) + "\n"
+ }
+
+ if err == io.EOF {
+ return nil
+ }
+ }
+}
+
+func (c *Commit) String() string {
+ return fmt.Sprintf(
+ "%s %s\nAuthor: %s\nDate: %s\n",
+ internal.CommitObject, c.Hash, c.Author.String(), c.Author.When,
+ )
+}
+
+type CommitIter struct {
+ iter
+}
+
+func NewCommitIter(r *Repository) *CommitIter {
+ return &CommitIter{newIter(r)}
+}
+
+func (i *CommitIter) Next() (*Commit, error) {
+ obj := <-i.ch
+ if obj == nil {
+ return nil, io.EOF
+ }
+
+ commit := &Commit{r: i.r}
+ return commit, commit.Decode(obj)
+}
+
+type iter struct {
+ ch chan internal.Object
+ r *Repository
+}
+
+func newIter(r *Repository) iter {
+ ch := make(chan internal.Object, 1)
+ return iter{ch, r}
+}
+
+func (i *iter) Add(o internal.Object) {
+ i.ch <- o
+}
+
+func (i *iter) Close() {
+ close(i.ch)
+}