| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "flag" |
| 6 | "strings" |
| 7 | "unicode" |
| 8 | "unicode/utf8" |
| 9 | ) |
| 10 | |
| 11 | const mutationMessageMaxRunes = 240 |
| 12 | |
| 13 | type mutationMessageCopy struct { |
| 14 | MessageHelp, NoPromptHelp, Prompt, Invalid string |
| 15 | } |
| 16 | |
| 17 | var mutationMessageText = mutationMessageCopy{ |
| 18 | MessageHelp: "Add a short note describing this change (shown alongside the recorded action).", |
| 19 | NoPromptHelp: "Skip the optional change description prompt.", |
| 20 | Prompt: "Describe this change (optional):", |
| 21 | Invalid: "Message must be one line and 240 characters or fewer.", |
| 22 | } |
| 23 | |
| 24 | func firstMutationMessage(messages []string) string { |
| 25 | if len(messages) == 0 { |
| 26 | return "" |
| 27 | } |
| 28 | return messages[0] |
| 29 | } |
| 30 | |
| 31 | type mutationMessageFlags struct { |
| 32 | message *string |
| 33 | noPrompt *bool |
| 34 | } |
| 35 | |
| 36 | func addMutationMessageFlags(fs *flag.FlagSet) mutationMessageFlags { |
| 37 | return mutationMessageFlags{ |
| 38 | message: fs.String("message", "", mutationMessageText.MessageHelp), |
| 39 | noPrompt: fs.Bool("no-prompt", false, mutationMessageText.NoPromptHelp), |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | func resolveMutationMessage(fs *flag.FlagSet, flags mutationMessageFlags) (string, error) { |
| 44 | if flagWasSet(fs, "message") { |
| 45 | return validateMutationMessage(*flags.message) |
| 46 | } |
| 47 | if *flags.noPrompt || !interactiveTerminal() { |
| 48 | return "", nil |
| 49 | } |
| 50 | pref, err := configMessagePrompt() |
| 51 | if err != nil { |
| 52 | return "", err |
| 53 | } |
| 54 | if pref == "off" { |
| 55 | return "", nil |
| 56 | } |
| 57 | return validateMutationMessage(promptLine(stdout, mutationMessageText.Prompt)) |
| 58 | } |
| 59 | |
| 60 | func validateMutationMessage(message string) (string, error) { |
| 61 | if !utf8.ValidString(message) || utf8.RuneCountInString(message) > mutationMessageMaxRunes { |
| 62 | return "", errors.New(mutationMessageText.Invalid) |
| 63 | } |
| 64 | for _, r := range message { |
| 65 | if unicode.IsControl(r) { |
| 66 | return "", errors.New(mutationMessageText.Invalid) |
| 67 | } |
| 68 | } |
| 69 | return strings.TrimSpace(message), nil |
| 70 | } |
| 71 | |