all operations now have an author and a timestamp

Michael Muré created

Change summary

bug/bug.go                       |  4 +++-
bug/comment.go                   |  4 ++--
bug/operation.go                 | 17 +++++++++++++++++
bug/operations/add_comment.go    | 15 ++++++---------
bug/operations/create.go         | 13 ++++---------
bug/operations/create_test.go    |  2 +-
bug/operations/set_status.go     |  9 ++++++---
bug/operations/set_title.go      | 11 ++++++++---
bug/snapshot.go                  | 12 ++++++++----
commands/close.go                |  7 ++++++-
commands/open.go                 |  7 ++++++-
tests/operation_iterator_test.go | 12 ++++++------
12 files changed, 73 insertions(+), 40 deletions(-)

Detailed changes

bug/bug.go 🔗

@@ -376,7 +376,9 @@ func (bug *Bug) Compile() Snapshot {
 	it := NewOperationIterator(bug)
 
 	for it.Next() {
-		snap = it.Value().Apply(snap)
+		op := it.Value()
+		snap = op.Apply(snap)
+		snap.Operations = append(snap.Operations, op)
 	}
 
 	return snap

bug/comment.go 🔗

@@ -8,9 +8,9 @@ type Comment struct {
 
 	// Creation time of the comment.
 	// Should be used only for human display, never for ordering as we can't rely on it in a distributed system.
-	Time int64
+	UnixTime int64
 }
 
 func (c Comment) FormatTime() string {
-	return time.Unix(c.Time, 0).Format(time.RFC822)
+	return time.Unix(c.UnixTime, 0).Format(time.RFC822)
 }

bug/operation.go 🔗

@@ -1,5 +1,7 @@
 package bug
 
+import "time"
+
 type OperationType int
 
 const (
@@ -12,13 +14,28 @@ const (
 
 type Operation interface {
 	OpType() OperationType
+	Time() time.Time
 	Apply(snapshot Snapshot) Snapshot
 }
 
 type OpBase struct {
 	OperationType OperationType
+	Author        Person
+	UnixTime      int64
+}
+
+func NewOpBase(opType OperationType, author Person) OpBase {
+	return OpBase{
+		OperationType: opType,
+		Author:        author,
+		UnixTime:      time.Now().Unix(),
+	}
 }
 
 func (op OpBase) OpType() OperationType {
 	return op.OperationType
 }
+
+func (op OpBase) Time() time.Time {
+	return time.Unix(op.UnixTime, 0)
+}

bug/operations/add_comment.go 🔗

@@ -2,32 +2,29 @@ package operations
 
 import (
 	"github.com/MichaelMure/git-bug/bug"
-	"time"
 )
 
+// AddCommentOperation will add a new comment in the bug
+
 var _ bug.Operation = AddCommentOperation{}
 
 type AddCommentOperation struct {
 	bug.OpBase
 	Message string
-	Author  bug.Person
-	Time    int64
 }
 
 func NewAddCommentOp(author bug.Person, message string) AddCommentOperation {
 	return AddCommentOperation{
-		OpBase:  bug.OpBase{OperationType: bug.AddCommentOp},
+		OpBase:  bug.NewOpBase(bug.AddCommentOp, author),
 		Message: message,
-		Author:  author,
-		Time:    time.Now().Unix(),
 	}
 }
 
 func (op AddCommentOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
 	comment := bug.Comment{
-		Message: op.Message,
-		Author:  op.Author,
-		Time:    op.Time,
+		Message:  op.Message,
+		Author:   op.Author,
+		UnixTime: op.UnixTime,
 	}
 
 	snapshot.Comments = append(snapshot.Comments, comment)

bug/operations/create.go 🔗

@@ -2,7 +2,6 @@ package operations
 
 import (
 	"github.com/MichaelMure/git-bug/bug"
-	"time"
 )
 
 // CreateOperation define the initial creation of a bug
@@ -13,17 +12,13 @@ type CreateOperation struct {
 	bug.OpBase
 	Title   string
 	Message string
-	Author  bug.Person
-	Time    int64
 }
 
 func NewCreateOp(author bug.Person, title, message string) CreateOperation {
 	return CreateOperation{
-		OpBase:  bug.OpBase{OperationType: bug.CreateOp},
+		OpBase:  bug.NewOpBase(bug.CreateOp, author),
 		Title:   title,
 		Message: message,
-		Author:  author,
-		Time:    time.Now().Unix(),
 	}
 }
 
@@ -31,9 +26,9 @@ func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
 	snapshot.Title = op.Title
 	snapshot.Comments = []bug.Comment{
 		{
-			Message: op.Message,
-			Author:  op.Author,
-			Time:    op.Time,
+			Message:  op.Message,
+			Author:   op.Author,
+			UnixTime: op.UnixTime,
 		},
 	}
 	return snapshot

bug/operations/create_test.go 🔗

@@ -21,7 +21,7 @@ func TestCreate(t *testing.T) {
 	expected := bug.Snapshot{
 		Title: "title",
 		Comments: []bug.Comment{
-			{Author: rene, Message: "message", Time: create.Time},
+			{Author: rene, Message: "message", UnixTime: create.UnixTime},
 		},
 	}
 

bug/operations/set_status.go 🔗

@@ -1,6 +1,8 @@
 package operations
 
-import "github.com/MichaelMure/git-bug/bug"
+import (
+	"github.com/MichaelMure/git-bug/bug"
+)
 
 // SetStatusOperation will change the status of a bug
 
@@ -11,14 +13,15 @@ type SetStatusOperation struct {
 	Status bug.Status
 }
 
-func NewSetStatusOp(status bug.Status) SetStatusOperation {
+func NewSetStatusOp(author bug.Person, status bug.Status) SetStatusOperation {
 	return SetStatusOperation{
-		OpBase: bug.OpBase{OperationType: bug.SetStatusOp},
+		OpBase: bug.NewOpBase(bug.SetStatusOp, author),
 		Status: status,
 	}
 }
 
 func (op SetStatusOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
 	snapshot.Status = op.Status
+
 	return snapshot
 }

bug/operations/set_title.go 🔗

@@ -1,6 +1,10 @@
 package operations
 
-import "github.com/MichaelMure/git-bug/bug"
+import (
+	"github.com/MichaelMure/git-bug/bug"
+)
+
+// SetTitleOperation will change the title of a bug
 
 var _ bug.Operation = SetTitleOperation{}
 
@@ -9,14 +13,15 @@ type SetTitleOperation struct {
 	Title string
 }
 
-func NewSetTitleOp(title string) SetTitleOperation {
+func NewSetTitleOp(author bug.Person, title string) SetTitleOperation {
 	return SetTitleOperation{
-		OpBase: bug.OpBase{OperationType: bug.SetTitleOp},
+		OpBase: bug.NewOpBase(bug.SetTitleOp, author),
 		Title:  title,
 	}
 }
 
 func (op SetTitleOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
 	snapshot.Title = op.Title
+
 	return snapshot
 }

bug/snapshot.go 🔗

@@ -7,11 +7,14 @@ import (
 
 // Snapshot is a compiled form of the Bug data structure used for storage and merge
 type Snapshot struct {
-	id       string
+	id string
+
 	Status   Status
 	Title    string
 	Comments []Comment
 	Labels   []Label
+
+	Operations []Operation
 }
 
 // Return the Bug identifier
@@ -32,10 +35,11 @@ func (snap Snapshot) Summary() string {
 	)
 }
 
+// Return the last time a bug was modified
 func (snap Snapshot) LastEdit() time.Time {
-	if len(snap.Comments) == 0 {
+	if len(snap.Operations) == 0 {
 		return time.Unix(0, 0)
 	}
-	lastEditTimestamp := snap.Comments[len(snap.Comments)-1].Time
-	return time.Unix(lastEditTimestamp, 0)
+
+	return snap.Operations[len(snap.Operations)-1].Time()
 }

commands/close.go 🔗

@@ -23,7 +23,12 @@ func runCloseBug(repo repository.Repo, args []string) error {
 		return err
 	}
 
-	op := operations.NewSetStatusOp(bug.ClosedStatus)
+	author, err := bug.GetUser(repo)
+	if err != nil {
+		return err
+	}
+
+	op := operations.NewSetStatusOp(author, bug.ClosedStatus)
 
 	b.Append(op)
 

commands/open.go 🔗

@@ -23,7 +23,12 @@ func runOpenBug(repo repository.Repo, args []string) error {
 		return err
 	}
 
-	op := operations.NewSetStatusOp(bug.OpenStatus)
+	author, err := bug.GetUser(repo)
+	if err != nil {
+		return err
+	}
+
+	op := operations.NewSetStatusOp(author, bug.OpenStatus)
 
 	b.Append(op)
 

tests/operation_iterator_test.go 🔗

@@ -13,11 +13,11 @@ var (
 		Email: "rene@descartes.fr",
 	}
 
-	createOp     = operations.NewCreateOp(rene, "title", "message")
-	setTitleOp   = operations.NewSetTitleOp("title2")
-	addCommentOp = operations.NewAddCommentOp(rene, "message2")
-	SetStatusOp  = operations.NewSetStatusOp(bug.ClosedStatus)
-	mockRepo     = repository.NewMockRepoForTest()
+	createOp      = operations.NewCreateOp(rene, "title", "message")
+	setTitleOp    = operations.NewSetTitleOp(rene, "title2")
+	addCommentOp  = operations.NewAddCommentOp(rene, "message2")
+	setStatusOp   = operations.NewSetStatusOp(rene, bug.ClosedStatus)
+	mockRepo      = repository.NewMockRepoForTest()
 )
 
 func TestOpIterator(t *testing.T) {
@@ -30,7 +30,7 @@ func TestOpIterator(t *testing.T) {
 
 	bug1.Append(createOp)
 	bug1.Append(setTitleOp)
-	bug1.Append(SetStatusOp)
+	bug1.Append(setStatusOp)
 	bug1.Commit(mockRepo)
 
 	bug1.Append(setTitleOp)