From 51e7beb72964bacea5b923c95bb1e6e10fa09836 Mon Sep 17 00:00:00 2001 From: vince Date: Fri, 10 Jul 2020 13:47:16 +0800 Subject: [PATCH] Add comment edit command This commit adds the comment edit command, which provides a CLI tool that allows a user to edit a comment. --- bug/op_add_comment.go | 5 +- bug/op_create.go | 5 +- commands/comment.go | 1 + commands/comment_edit.go | 102 +++++++++++++++++++++++++++++++++++++++ commands/show.go | 3 +- 5 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 commands/comment_edit.go diff --git a/bug/op_add_comment.go b/bug/op_add_comment.go index 4d1fa271d2ed2075a5380e3387f42a8a9e05209b..9a513f52a75e5354c443643bafb0352e55f93b77 100644 --- a/bug/op_add_comment.go +++ b/bug/op_add_comment.go @@ -36,8 +36,9 @@ func (op *AddCommentOperation) Apply(snapshot *Snapshot) { snapshot.addActor(op.Author) snapshot.addParticipant(op.Author) + commentId := entity.Id(CompileCommentId(snapshot.Id().String(), op.Id().String())) comment := Comment{ - id: entity.Id(CompileCommentId(snapshot.Id().String(), op.Id().String())), + id: commentId, Message: op.Message, Author: op.Author, Files: op.Files, @@ -47,7 +48,7 @@ func (op *AddCommentOperation) Apply(snapshot *Snapshot) { snapshot.Comments = append(snapshot.Comments, comment) item := &AddCommentTimelineItem{ - CommentTimelineItem: NewCommentTimelineItem(op.Id(), comment), + CommentTimelineItem: NewCommentTimelineItem(commentId, comment), } snapshot.Timeline = append(snapshot.Timeline, item) diff --git a/bug/op_create.go b/bug/op_create.go index 49c941974120f2617b8448e705e81cb0cace89e1..19ce4834cd52db730044891a104f12261182c7fc 100644 --- a/bug/op_create.go +++ b/bug/op_create.go @@ -39,8 +39,9 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) { snapshot.Title = op.Title + commentId := entity.Id(CompileCommentId(snapshot.Id().String(), op.Id().String())) comment := Comment{ - id: entity.Id(CompileCommentId(snapshot.Id().String(), op.Id().String())), + id: commentId, Message: op.Message, Author: op.Author, UnixTime: timestamp.Timestamp(op.UnixTime), @@ -52,7 +53,7 @@ func (op *CreateOperation) Apply(snapshot *Snapshot) { snapshot.Timeline = []TimelineItem{ &CreateTimelineItem{ - CommentTimelineItem: NewCommentTimelineItem(op.Id(), comment), + CommentTimelineItem: NewCommentTimelineItem(commentId, comment), }, } } diff --git a/commands/comment.go b/commands/comment.go index e81405a64be980bd114aa3db7841a132ce50b9b9..4fca0666259730972d3fdff3ccf417210b24e930 100644 --- a/commands/comment.go +++ b/commands/comment.go @@ -22,6 +22,7 @@ func newCommentCommand() *cobra.Command { } cmd.AddCommand(newCommentAddCommand()) + cmd.AddCommand(newCommentEditCommand()) return cmd } diff --git a/commands/comment_edit.go b/commands/comment_edit.go new file mode 100644 index 0000000000000000000000000000000000000000..e190a8427d002d8ac4b19ad0c2b5df8e40ef469b --- /dev/null +++ b/commands/comment_edit.go @@ -0,0 +1,102 @@ +package commands + +import ( + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/MichaelMure/git-bug/bug" + "github.com/MichaelMure/git-bug/cache" + _select "github.com/MichaelMure/git-bug/commands/select" + "github.com/MichaelMure/git-bug/entity" + "github.com/MichaelMure/git-bug/input" +) + +type commentEditOptions struct { + messageFile string + message string +} + +func newCommentEditCommand() *cobra.Command { + env := newEnv() + options := commentEditOptions{} + + cmd := &cobra.Command{ + Use: "edit []", + Short: "Edit an existing comment on a bug.", + PreRunE: loadBackendEnsureUser(env), + PostRunE: closeBackend(env), + RunE: func(cmd *cobra.Command, args []string) error { + return runCommentEdit(env, options, args) + }, + } + + flags := cmd.Flags() + flags.SortFlags = false + + flags.StringVarP(&options.messageFile, "file", "F", "", + "Take the message from the given file. Use - to read the message from the standard input") + + flags.StringVarP(&options.message, "message", "m", "", + "Provide the new message from the command line") + + return cmd +} + +func ResolveComment(repo *cache.RepoCache, args []string) (*cache.BugCache, entity.Id, error) { + fullId := args[0] + bugId, _ := bug.UnpackCommentId(args[0]) + args[0] = bugId + b, args, err := _select.ResolveBug(repo, args) + if err != nil { + return nil, entity.UnsetId, err + } + + matching := make([]entity.Id, 0, 5) + + for _, comment := range b.Snapshot().Comments { + if comment.Id().HasPrefix(fullId) { + matching = append(matching, comment.Id()) + } + } + + if len(matching) > 1 { + return nil, entity.UnsetId, entity.NewErrMultipleMatch("comment", matching) + } else if len(matching) == 0 { + return nil, entity.UnsetId, errors.New("comment doesn't exist") + } + + return b, matching[0], nil +} + +func runCommentEdit(env *Env, opts commentEditOptions, args []string) error { + b, c, err := ResolveComment(env.backend, args) + + if err != nil { + return err + } + + if opts.messageFile != "" && opts.message == "" { + opts.message, err = input.BugCommentFileInput(opts.messageFile) + if err != nil { + return err + } + } + + if opts.messageFile == "" && opts.message == "" { + opts.message, err = input.BugCommentEditorInput(env.backend, "") + if err == input.ErrEmptyMessage { + env.err.Println("Empty message, aborting.") + return nil + } + if err != nil { + return err + } + } + + _, err = b.EditComment(c, opts.message) + if err != nil { + return err + } + + return b.Commit() +} diff --git a/commands/show.go b/commands/show.go index f39952050ba16236c13088208d0001174c42a752..107e42191a2cd08b3b67b100f511b34dd8171454 100644 --- a/commands/show.go +++ b/commands/show.go @@ -158,8 +158,9 @@ func showDefaultFormatter(env *Env, snapshot *bug.Snapshot) error { for i, comment := range snapshot.Comments { var message string - env.out.Printf("%s#%d %s <%s>\n\n", + env.out.Printf("%s%s #%d %s <%s>\n\n", indent, + comment.Id().Human(), i, comment.Author.DisplayName(), comment.Author.Email(),