wip: tweak output, update to Prompter, start on tests
This commit is contained in:
parent
5a6b4ce934
commit
b52d452168
4 changed files with 107 additions and 29 deletions
|
|
@ -45,10 +45,10 @@ func NewCmdIssue(f *cmdutil.Factory) *cobra.Command {
|
|||
cmd.AddCommand(cmdClose.NewCmdClose(f, nil))
|
||||
cmd.AddCommand(cmdCreate.NewCmdCreate(f, nil))
|
||||
cmd.AddCommand(cmdList.NewCmdList(f, nil))
|
||||
cmd.AddCommand(cmdLock.NewCmdLock(f, cmd.Name()))
|
||||
cmd.AddCommand(cmdLock.NewCmdLock(f, cmd.Name(), nil))
|
||||
cmd.AddCommand(cmdReopen.NewCmdReopen(f, nil))
|
||||
cmd.AddCommand(cmdStatus.NewCmdStatus(f, nil))
|
||||
cmd.AddCommand(cmdLock.NewCmdUnlock(f, cmd.Name()))
|
||||
cmd.AddCommand(cmdLock.NewCmdUnlock(f, cmd.Name(), nil))
|
||||
cmd.AddCommand(cmdView.NewCmdView(f, nil))
|
||||
cmd.AddCommand(cmdComment.NewCmdComment(f, nil))
|
||||
cmd.AddCommand(cmdDelete.NewCmdDelete(f, nil))
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
package lock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/cli/cli/v2/api"
|
||||
"github.com/cli/cli/v2/internal/config"
|
||||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
|
|
@ -26,6 +26,13 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type iprompter interface {
|
||||
Confirm(string, bool) (bool, error)
|
||||
}
|
||||
|
||||
// TODO cmd tests
|
||||
// TODO run tests
|
||||
|
||||
// reasons contains all possible lock reasons allowed by GitHub.
|
||||
//
|
||||
// We don't directly construct a map so that we can maintain the reasons in
|
||||
|
|
@ -84,6 +91,7 @@ type LockOptions struct {
|
|||
Config func() (config.Config, error)
|
||||
IO *iostreams.IOStreams
|
||||
BaseRepo func() (ghrepo.Interface, error)
|
||||
Prompter iprompter
|
||||
|
||||
Fields []string
|
||||
ParentCmd string
|
||||
|
|
@ -92,7 +100,6 @@ type LockOptions struct {
|
|||
}
|
||||
|
||||
func (opts *LockOptions) setCommonOptions(f *cmdutil.Factory, cmd *cobra.Command, args []string) {
|
||||
|
||||
opts.IO = f.IOStreams
|
||||
opts.HttpClient = f.HttpClient
|
||||
opts.Config = f.Config
|
||||
|
|
@ -107,10 +114,11 @@ func (opts *LockOptions) setCommonOptions(f *cmdutil.Factory, cmd *cobra.Command
|
|||
|
||||
}
|
||||
|
||||
func NewCmdLock(f *cmdutil.Factory, parentName string) *cobra.Command {
|
||||
|
||||
func NewCmdLock(f *cmdutil.Factory, parentName string, runF func(string, *LockOptions) error) *cobra.Command {
|
||||
opts := &LockOptions{ParentCmd: parentName}
|
||||
|
||||
opts.Prompter = f.Prompter
|
||||
|
||||
c := alias[opts.ParentCmd]
|
||||
short := fmt.Sprintf("Lock %s conversation", strings.ToLower(c.FullName))
|
||||
|
||||
|
|
@ -119,21 +127,28 @@ func NewCmdLock(f *cmdutil.Factory, parentName string) *cobra.Command {
|
|||
Short: short,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
opts.setCommonOptions(f, cmd, args)
|
||||
|
||||
reasonProvided := cmd.Flags().Changed("message")
|
||||
if reasonProvided {
|
||||
_, ok := reasonsMap[opts.Reason]
|
||||
if !ok {
|
||||
cs := opts.IO.ColorScheme()
|
||||
if opts.IO.IsStdoutTTY() {
|
||||
cs := opts.IO.ColorScheme()
|
||||
|
||||
return cmdutil.FlagErrorf("%s Invalid reason: %v\nAborting lock. See help for options.",
|
||||
cs.FailureIconWithColor(cs.Red), opts.Reason)
|
||||
return cmdutil.FlagErrorf("%s Invalid reason: %v\nAborting lock. See help for options.",
|
||||
cs.FailureIconWithColor(cs.Red), opts.Reason)
|
||||
|
||||
} else {
|
||||
return fmt.Errorf("invalid reason %s", opts.Reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return padlock(Lock, opts)
|
||||
if runF != nil {
|
||||
return runF(Lock, opts)
|
||||
}
|
||||
return lock(Lock, opts)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -143,8 +158,7 @@ func NewCmdLock(f *cmdutil.Factory, parentName string) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func NewCmdUnlock(f *cmdutil.Factory, parentName string) *cobra.Command {
|
||||
|
||||
func NewCmdUnlock(f *cmdutil.Factory, parentName string, runF func(string, *LockOptions) error) *cobra.Command {
|
||||
opts := &LockOptions{ParentCmd: parentName}
|
||||
|
||||
c := alias[opts.ParentCmd]
|
||||
|
|
@ -158,7 +172,10 @@ func NewCmdUnlock(f *cmdutil.Factory, parentName string) *cobra.Command {
|
|||
|
||||
opts.setCommonOptions(f, cmd, args)
|
||||
|
||||
return padlock(Unlock, opts)
|
||||
if runF != nil {
|
||||
return runF(Unlock, opts)
|
||||
}
|
||||
return lock(Unlock, opts)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -182,13 +199,12 @@ func reason(reason string) string {
|
|||
//
|
||||
// Example output: "Locked as RESOLVED: Issue #31 (Title of issue)"
|
||||
func status(state string, lockable *api.Issue, opts *LockOptions) string {
|
||||
|
||||
return fmt.Sprintf("%sed%s: %s #%d (%s)",
|
||||
state, reason(opts.Reason), alias[opts.ParentCmd].FullName, lockable.Number, lockable.Title)
|
||||
}
|
||||
|
||||
// padlock will lock or unlock a conversation.
|
||||
func padlock(state string, opts *LockOptions) error {
|
||||
// lock will lock or unlock a conversation.
|
||||
func lock(state string, opts *LockOptions) error {
|
||||
cs := opts.IO.ColorScheme()
|
||||
|
||||
httpClient, err := opts.HttpClient()
|
||||
|
|
@ -243,14 +259,15 @@ func padlock(state string, opts *LockOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(opts.IO.ErrOut, successMsg)
|
||||
if opts.IO.IsStdoutTTY() {
|
||||
fmt.Fprint(opts.IO.ErrOut, successMsg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// lockLockable will lock an issue or pull request
|
||||
func lockLockable(httpClient *http.Client, repo ghrepo.Interface, lockable *api.Issue, opts *LockOptions) error {
|
||||
|
||||
var mutation struct {
|
||||
LockLockable struct {
|
||||
LockedRecord struct {
|
||||
|
|
@ -298,17 +315,16 @@ func unlockLockable(httpClient *http.Client, repo ghrepo.Interface, lockable *ap
|
|||
// lockable item that is already locked; it will just ignore that request. You
|
||||
// need to first unlock then lock with a new reason.
|
||||
func relockLockable(httpClient *http.Client, repo ghrepo.Interface, lockable *api.Issue, opts *LockOptions) (bool, error) {
|
||||
|
||||
var relocked bool
|
||||
shouldRelock := &survey.Confirm{
|
||||
Message: fmt.Sprintf("%s #%d already locked%s. Unlock and lock again%s?",
|
||||
alias[opts.ParentCmd].FullName, lockable.Number, reason(lockable.ActiveLockReason), reason(opts.Reason)),
|
||||
Default: true,
|
||||
if !opts.IO.CanPrompt() {
|
||||
return false, errors.New("already locked")
|
||||
}
|
||||
|
||||
err := survey.AskOne(shouldRelock, &relocked)
|
||||
prompt := fmt.Sprintf("%s #%d already locked%s. Unlock and lock again%s?",
|
||||
alias[opts.ParentCmd].FullName, lockable.Number, reason(lockable.ActiveLockReason), reason(opts.Reason))
|
||||
|
||||
relocked, err := opts.Prompter.Confirm(prompt, true)
|
||||
if err != nil {
|
||||
return relocked, err
|
||||
return false, err
|
||||
} else if !relocked {
|
||||
return relocked, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,74 @@
|
|||
package lock
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cli/cli/v2/pkg/cmdutil"
|
||||
"github.com/cli/cli/v2/pkg/iostreams"
|
||||
"github.com/google/shlex"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_NewCmdLock(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
args string
|
||||
want LockOptions
|
||||
wantErr string
|
||||
tty bool
|
||||
}{
|
||||
// TODO
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ios, _, _, _ := iostreams.Test()
|
||||
ios.SetStdoutTTY(tt.tty)
|
||||
ios.SetStdinTTY(tt.tty)
|
||||
ios.SetStderrTTY(tt.tty)
|
||||
f := &cmdutil.Factory{
|
||||
IOStreams: ios,
|
||||
}
|
||||
var opts *LockOptions
|
||||
cmd := NewCmdLock(f, "issue", func(_ string, o *LockOptions) error {
|
||||
opts = o
|
||||
return nil
|
||||
})
|
||||
cmd.PersistentFlags().StringP("repo", "R", "", "")
|
||||
|
||||
argv, err := shlex.Split(tt.args)
|
||||
assert.NoError(t, err)
|
||||
|
||||
cmd.SetArgs(argv)
|
||||
cmd.SetIn(&bytes.Buffer{})
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
|
||||
_, err = cmd.ExecuteC()
|
||||
if tt.wantErr != "" {
|
||||
assert.EqualError(t, err, tt.wantErr)
|
||||
return
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.want.Reason, opts.Reason)
|
||||
assert.Equal(t, tt.want.SelectorArg, opts.SelectorArg)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_lock(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func Test_NewCmdUnlock(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func TestReasons(t *testing.T) {
|
||||
assert.Equal(t, len(reasons), len(reasonsApi))
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ func NewCmdPR(f *cmdutil.Factory) *cobra.Command {
|
|||
cmd.AddCommand(cmdCreate.NewCmdCreate(f, nil))
|
||||
cmd.AddCommand(cmdDiff.NewCmdDiff(f, nil))
|
||||
cmd.AddCommand(cmdList.NewCmdList(f, nil))
|
||||
cmd.AddCommand(cmdLock.NewCmdLock(f, cmd.Name()))
|
||||
cmd.AddCommand(cmdLock.NewCmdLock(f, cmd.Name(), nil))
|
||||
cmd.AddCommand(cmdMerge.NewCmdMerge(f, nil))
|
||||
cmd.AddCommand(cmdReady.NewCmdReady(f, nil))
|
||||
cmd.AddCommand(cmdReopen.NewCmdReopen(f, nil))
|
||||
cmd.AddCommand(cmdReview.NewCmdReview(f, nil))
|
||||
cmd.AddCommand(cmdStatus.NewCmdStatus(f, nil))
|
||||
cmd.AddCommand(cmdLock.NewCmdUnlock(f, cmd.Name()))
|
||||
cmd.AddCommand(cmdLock.NewCmdUnlock(f, cmd.Name(), nil))
|
||||
cmd.AddCommand(cmdView.NewCmdView(f, nil))
|
||||
cmd.AddCommand(cmdChecks.NewCmdChecks(f, nil))
|
||||
cmd.AddCommand(cmdComment.NewCmdComment(f, nil))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue