commands: display comment's id in "git bug comment"

Michael Muré created

Change summary

bug/comment.go            | 16 ++++++++++++++++
bug/op_add_comment.go     | 15 ++++++++-------
bug/op_create.go          | 15 ++++++++-------
bug/op_create_test.go     |  7 ++++++-
bug/op_edit_comment.go    |  1 +
bug/operation.go          |  3 +++
commands/comment.go       |  1 +
identity/identity_stub.go |  1 +
8 files changed, 44 insertions(+), 15 deletions(-)

Detailed changes

bug/comment.go 🔗

@@ -9,6 +9,7 @@ import (
 
 // Comment represent a comment in a Bug
 type Comment struct {
+	id      string
 	Author  identity.Interface
 	Message string
 	Files   []git.Hash
@@ -18,6 +19,21 @@ type Comment struct {
 	UnixTime timestamp.Timestamp
 }
 
+// Id return the Comment identifier
+func (c Comment) Id() string {
+	if c.id == "" {
+		// simply panic as it would be a coding error
+		// (using an id of an identity not stored yet)
+		panic("no id yet")
+	}
+	return c.id
+}
+
+// HumanId return the Comment identifier truncated for human consumption
+func (c Comment) HumanId() string {
+	return FormatHumanID(c.Id())
+}
+
 // FormatTimeRel format the UnixTime of the comment for human consumption
 func (c Comment) FormatTimeRel() string {
 	return humanize.Time(c.UnixTime.Time())

bug/op_add_comment.go 🔗

@@ -29,7 +29,15 @@ func (op *AddCommentOperation) Hash() (git.Hash, error) {
 }
 
 func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
+	hash, err := op.Hash()
+	if err != nil {
+		// Should never error unless a programming error happened
+		// (covered in OpBase.Validate())
+		panic(err)
+	}
+
 	comment := Comment{
+		id:       string(hash),
 		Message:  op.Message,
 		Author:   op.Author,
 		Files:    op.Files,
@@ -38,13 +46,6 @@ func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
 
 	snapshot.Comments = append(snapshot.Comments, comment)
 
-	hash, err := op.Hash()
-	if err != nil {
-		// Should never error unless a programming error happened
-		// (covered in OpBase.Validate())
-		panic(err)
-	}
-
 	item := &AddCommentTimelineItem{
 		CommentTimelineItem: NewCommentTimelineItem(hash, comment),
 	}

bug/op_create.go 🔗

@@ -30,9 +30,17 @@ func (op *CreateOperation) Hash() (git.Hash, error) {
 }
 
 func (op *CreateOperation) Apply(snapshot *Snapshot) {
+	hash, err := op.Hash()
+	if err != nil {
+		// Should never error unless a programming error happened
+		// (covered in OpBase.Validate())
+		panic(err)
+	}
+
 	snapshot.Title = op.Title
 
 	comment := Comment{
+		id:       string(hash),
 		Message:  op.Message,
 		Author:   op.Author,
 		UnixTime: timestamp.Timestamp(op.UnixTime),
@@ -42,13 +50,6 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) {
 	snapshot.Author = op.Author
 	snapshot.CreatedAt = op.Time()
 
-	hash, err := op.Hash()
-	if err != nil {
-		// Should never error unless a programming error happened
-		// (covered in OpBase.Validate())
-		panic(err)
-	}
-
 	snapshot.Timeline = []TimelineItem{
 		&CreateTimelineItem{
 			CommentTimelineItem: NewCommentTimelineItem(hash, comment),

bug/op_create_test.go 🔗

@@ -23,7 +23,12 @@ func TestCreate(t *testing.T) {
 	hash, err := create.Hash()
 	assert.NoError(t, err)
 
-	comment := Comment{Author: rene, Message: "message", UnixTime: timestamp.Timestamp(create.UnixTime)}
+	comment := Comment{
+		id:       string(hash),
+		Author:   rene,
+		Message:  "message",
+		UnixTime: timestamp.Timestamp(create.UnixTime),
+	}
 
 	expected := Snapshot{
 		Title: "title",

bug/op_edit_comment.go 🔗

@@ -57,6 +57,7 @@ func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
 	}
 
 	comment := Comment{
+		id:       string(op.Target),
 		Message:  op.Message,
 		Files:    op.Files,
 		UnixTime: timestamp.Timestamp(op.UnixTime),

bug/operation.go 🔗

@@ -60,6 +60,9 @@ func hashRaw(data []byte) git.Hash {
 
 // hash compute the hash of the serialized operation
 func hashOperation(op Operation) (git.Hash, error) {
+	// TODO: this might not be the best idea: if a single bit change in the output of json.Marshal, this will break.
+	// Idea: hash the segment of serialized data (= immutable) instead of the go object in memory
+
 	base := op.base()
 
 	if base.hash != "" {

commands/comment.go 🔗

@@ -39,6 +39,7 @@ func commentsTextOutput(comments []bug.Comment) {
 		}
 
 		fmt.Printf("Author: %s\n", colors.Magenta(comment.Author.DisplayName()))
+		fmt.Printf("Id: %s\n", colors.Cyan(comment.HumanId()))
 		fmt.Printf("Date: %s\n\n", comment.FormatTime())
 		fmt.Println(text.LeftPad(comment.Message, 4))
 	}

identity/identity_stub.go 🔗

@@ -20,6 +20,7 @@ type IdentityStub struct {
 }
 
 func (i *IdentityStub) MarshalJSON() ([]byte, error) {
+	// TODO: add a type marker
 	return json.Marshal(struct {
 		Id string `json:"id"`
 	}{