From cb0d5c34a6e6aa194e4f8f3a5e089fa8857c9c2d Mon Sep 17 00:00:00 2001 From: Gregor Riegler Date: Wed, 21 Sep 2022 21:07:33 +0200 Subject: [PATCH] Refactor: Extract say to its own file (#312) --- coauthors.go | 21 +-- mob.go | 472 +++++++++++++++++++++----------------------------- mob_test.go | 19 +- say/say.go | 84 +++++++++ squash_wip.go | 13 +- 5 files changed, 312 insertions(+), 297 deletions(-) create mode 100644 say/say.go diff --git a/coauthors.go b/coauthors.go index 96f889b4..72b0ccaf 100644 --- a/coauthors.go +++ b/coauthors.go @@ -3,6 +3,7 @@ package main import ( "bufio" "fmt" + "github.com/remotemobprogramming/mob/v3/say" "os" "path" "regexp" @@ -24,20 +25,20 @@ func collectCoauthorsFromWipCommits(file *os.File) []Author { // For details and background, see https://github.com/remotemobprogramming/mob/issues/81 coauthors := parseCoauthors(file) - debugInfo("Parsed coauthors") - debugInfo(strings.Join(coauthors, ",")) + say.Debug("Parsed coauthors") + say.Debug(strings.Join(coauthors, ",")) coauthors = removeElementsContaining(coauthors, gitUserEmail()) - debugInfo("Parsed coauthors without committer") - debugInfo(strings.Join(coauthors, ",")) + say.Debug("Parsed coauthors without committer") + say.Debug(strings.Join(coauthors, ",")) coauthors = removeDuplicateValues(coauthors) - debugInfo("Unique coauthors without committer") - debugInfo(strings.Join(coauthors, ",")) + say.Debug("Unique coauthors without committer") + say.Debug(strings.Join(coauthors, ",")) sortByLength(coauthors) - debugInfo("Sorted unique coauthors without committer") - debugInfo(strings.Join(coauthors, ",")) + say.Debug("Sorted unique coauthors without committer") + say.Debug(strings.Join(coauthors, ",")) return coauthors } @@ -94,11 +95,11 @@ func removeDuplicateValues(slice []string) []string { func appendCoauthorsToSquashMsg(gitDir string) error { squashMsgPath := path.Join(gitDir, "SQUASH_MSG") - debugInfo("opening " + squashMsgPath) + say.Debug("opening " + squashMsgPath) file, err := os.OpenFile(squashMsgPath, os.O_APPEND|os.O_RDWR, 0644) if err != nil { if os.IsNotExist(err) { - debugInfo(squashMsgPath + " does not exist") + say.Debug(squashMsgPath + " does not exist") // No wip commits, nothing to squash, this isn't really an error return nil } diff --git a/mob.go b/mob.go index d689dfea..7ae7131e 100644 --- a/mob.go +++ b/mob.go @@ -8,6 +8,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/remotemobprogramming/mob/v3/say" "io/ioutil" "net/http" "net/url" @@ -27,7 +28,6 @@ const ( var ( workingDir = "" - Debug = false // override with --debug parameter GitPassthroughStderrStdout = false // hack to get git hooks to print to stdout/stderr ) @@ -130,8 +130,8 @@ func (branch Branch) remote(configuration Configuration) Branch { func (branch Branch) hasRemoteBranch(configuration Configuration) bool { remoteBranches := gitRemoteBranches() remoteBranch := branch.remote(configuration).Name - debugInfo("Remote Branches: " + strings.Join(remoteBranches, "\n")) - debugInfo("Remote Branch: " + remoteBranch) + say.Debug("Remote Branches: " + strings.Join(remoteBranches, "\n")) + say.Debug("Remote Branch: " + remoteBranch) for i := 0; i < len(remoteBranches); i++ { if remoteBranches[i] == remoteBranch { @@ -233,7 +233,7 @@ func (branch Branch) hasUnpushedCommits(configuration Configuration) bool { } unpushedCommits := unpushedCount != 0 if unpushedCommits { - sayInfo(fmt.Sprintf("there are %d unpushed commits on local base branch <%s>", unpushedCount, branch.Name)) + say.Info(fmt.Sprintf("there are %d unpushed commits on local base branch <%s>", unpushedCount, branch.Name)) } return unpushedCommits } @@ -249,11 +249,11 @@ func stringContains(list []string, element string) bool { } func main() { - parseDebug(os.Args) - debugInfo(runtime.Version()) + say.TurnOnDebuggingByArgs(os.Args) + say.Debug(runtime.Version()) if !isGitInstalled() { - sayError("'git' command was not found in PATH. It may be not installed. " + + say.Error("'git' command was not found in PATH. It may be not installed. " + "To learn how to install 'git' refer to https://git-scm.com/book/en/v2/Getting-Started-Installing-Git.") exit(1) } @@ -267,18 +267,18 @@ func main() { if isGit() { configuration = parseProjectConfiguration(configuration, gitRootDir()+"/.mob") } - debugInfo("Args '" + strings.Join(os.Args, " ") + "'") + say.Debug("Args '" + strings.Join(os.Args, " ") + "'") currentCliName := currentCliName(os.Args[0]) if currentCliName != configuration.CliName { - debugInfo("Updating cli name to " + currentCliName) + say.Debug("Updating cli name to " + currentCliName) configuration.CliName = currentCliName } command, parameters, configuration := parseArgs(os.Args, configuration) - debugInfo("command '" + command + "'") - debugInfo("parameters '" + strings.Join(parameters, " ") + "'") - debugInfo("version " + versionNumber) - debugInfo("workingDir '" + workingDir + "'") + say.Debug("command '" + command + "'") + say.Debug("parameters '" + strings.Join(parameters, " ") + "'") + say.Debug("version " + versionNumber) + say.Debug("workingDir '" + workingDir + "'") // workaround until we have a better design if configuration.GitHooksEnabled { @@ -338,16 +338,6 @@ func getDefaultConfiguration() Configuration { } } -func parseDebug(args []string) { - // debug needs to be parsed at the beginning to have DEBUG enabled as quickly as possible - // otherwise, parsing others or other parameters don't have debug enabled - for i := 0; i < len(args); i++ { - if args[i] == "--debug" { - Debug = true - } - } -} - func (c Configuration) mob(command string) string { return c.CliName + " " + command } @@ -356,25 +346,25 @@ func parseUserConfiguration(configuration Configuration, path string) Configurat file, err := os.Open(path) if err != nil { - debugInfo("No user configuration file found. (" + path + ") Error: " + err.Error()) + say.Debug("No user configuration file found. (" + path + ") Error: " + err.Error()) return configuration } else { - debugInfo("Found user configuration file at " + path) + say.Debug("Found user configuration file at " + path) } fileScanner := bufio.NewScanner(file) for fileScanner.Scan() { line := strings.TrimSpace(fileScanner.Text()) - debugInfo(line) + say.Debug(line) if !strings.Contains(line, "=") { - debugInfo("Skip line because line contains no =. Line=" + line) + say.Debug("Skip line because line contains no =. Line=" + line) continue } key := line[0:strings.Index(line, "=")] value := strings.TrimPrefix(line, key+"=") - debugInfo("Key is " + key) - debugInfo("Value is " + value) + say.Debug("Key is " + key) + say.Debug("Value is " + value) switch key { case "MOB_CLI_NAME": setUnquotedString(&configuration.CliName, key, value) @@ -435,7 +425,7 @@ func parseUserConfiguration(configuration Configuration, path string) Configurat } if err := fileScanner.Err(); err != nil { - sayWarning("User configuration file exists, but could not be read. (" + path + ")") + say.Warning("User configuration file exists, but could not be read. (" + path + ")") } return configuration @@ -445,28 +435,28 @@ func parseProjectConfiguration(configuration Configuration, path string) Configu file, err := os.Open(path) if err != nil { - debugInfo("No project configuration file found. (" + path + ") Error: " + err.Error()) + say.Debug("No project configuration file found. (" + path + ") Error: " + err.Error()) return configuration } else { - debugInfo("Found project configuration file at " + path) + say.Debug("Found project configuration file at " + path) } fileScanner := bufio.NewScanner(file) for fileScanner.Scan() { line := strings.TrimSpace(fileScanner.Text()) - debugInfo(line) + say.Debug(line) if !strings.Contains(line, "=") { - debugInfo("Skip line because line contains no =. Line=" + line) + say.Debug("Skip line because line contains no =. Line=" + line) continue } key := line[0:strings.Index(line, "=")] value := strings.TrimPrefix(line, key+"=") - debugInfo("Key is " + key) - debugInfo("Value is " + value) + say.Debug("Key is " + key) + say.Debug("Value is " + value) switch key { case "MOB_VOICE_COMMAND", "MOB_VOICE_MESSAGE", "MOB_NOTIFY_COMMAND", "MOB_NOTIFY_MESSAGE", "MOB_OPEN_COMMAND": - sayWarning("Skipped overwriting key " + key + " from project/.mob file out of security reasons!") + say.Warning("Skipped overwriting key " + key + " from project/.mob file out of security reasons!") case "MOB_CLI_NAME": setUnquotedString(&configuration.CliName, key, value) case "MOB_REMOTE_NAME": @@ -516,7 +506,7 @@ func parseProjectConfiguration(configuration Configuration, path string) Configu } if err := fileScanner.Err(); err != nil { - sayWarning("Project configuration file exists, but could not be read. (" + path + ")") + say.Warning("Project configuration file exists, but could not be read. (" + path + ")") } return configuration @@ -525,35 +515,35 @@ func parseProjectConfiguration(configuration Configuration, path string) Configu func setUnquotedString(s *string, key string, value string) { unquotedValue, err := strconv.Unquote(value) if err != nil { - sayWarning("Could not set key from configuration file because value is not parseable (" + key + "=" + value + ")") + say.Warning("Could not set key from configuration file because value is not parseable (" + key + "=" + value + ")") return } *s = unquotedValue - debugInfo("Overwriting " + key + " =" + unquotedValue) + say.Debug("Overwriting " + key + " =" + unquotedValue) } func setBoolean(s *bool, key string, value string) { boolValue, err := strconv.ParseBool(value) if err != nil { - sayWarning("Could not set key from configuration file because value is not parseable (" + key + "=" + value + ")") + say.Warning("Could not set key from configuration file because value is not parseable (" + key + "=" + value + ")") return } *s = boolValue - debugInfo("Overwriting " + key + " =" + strconv.FormatBool(boolValue)) + say.Debug("Overwriting " + key + " =" + strconv.FormatBool(boolValue)) } func setMobDoneSquash(configuration *Configuration, key string, value string) { if strings.HasPrefix(value, "\"") { unquotedValue, err := strconv.Unquote(value) if err != nil { - sayWarning("Could not set key from configuration file because value is not parseable (" + key + "=" + value + ")") + say.Warning("Could not set key from configuration file because value is not parseable (" + key + "=" + value + ")") return } value = unquotedValue } printDeprecatedDoneSquashMessage(value) configuration.DoneSquash = doneSquash(value) - debugInfo("Overwriting " + key + " =" + string(configuration.DoneSquash)) + say.Debug("Overwriting " + key + " =" + string(configuration.DoneSquash)) } func parseEnvironmentVariables(configuration Configuration) Configuration { @@ -608,7 +598,7 @@ func setStringFromEnvVariable(s *string, key string) { value, set := os.LookupEnv(key) if set && value != "" { *s = value - debugInfo("overriding " + key + "=" + *s) + say.Debug("overriding " + key + "=" + *s) } } @@ -616,7 +606,7 @@ func setOptionalStringFromEnvVariable(s *string, key string) { value, set := os.LookupEnv(key) if set { *s = value - debugInfo("overriding " + key + "=" + *s) + say.Debug("overriding " + key + "=" + *s) } } @@ -626,17 +616,17 @@ func setBoolFromEnvVariable(s *bool, key string) { return } if value == "" { - debugInfo("ignoring " + key + "=" + value + " (empty string)") + say.Debug("ignoring " + key + "=" + value + " (empty string)") } if value == "true" { *s = true - debugInfo("overriding " + key + "=" + strconv.FormatBool(*s)) + say.Debug("overriding " + key + "=" + strconv.FormatBool(*s)) } else if value == "false" { *s = false - debugInfo("overriding " + key + "=" + strconv.FormatBool(*s)) + say.Debug("overriding " + key + "=" + strconv.FormatBool(*s)) } else { - sayWarning("ignoring " + key + "=" + value + " (not a boolean)") + say.Warning("ignoring " + key + "=" + value + " (not a boolean)") } } @@ -649,11 +639,11 @@ func setDoneSquashFromEnvVariable(configuration *Configuration, key string) { configuration.DoneSquash = doneSquash(value) if value == "" { - debugInfo("ignoring " + key + "=" + value + " (empty string)") + say.Debug("ignoring " + key + "=" + value + " (empty string)") return } - debugInfo("overriding " + key + "=" + string(configuration.DoneSquash)) + say.Debug("overriding " + key + "=" + string(configuration.DoneSquash)) } func printDeprecatedDoneSquashMessage(value string) { @@ -664,55 +654,55 @@ func printDeprecatedDoneSquashMessage(value string) { if unquotedValue == "true" || unquotedValue == "false" { newValue := doneSquash(unquotedValue) - say("MOB_DONE_SQUASH is set to the deprecated value " + value + ". Use the value " + newValue + " instead.") + say.Say("MOB_DONE_SQUASH is set to the deprecated value " + value + ". Use the value " + newValue + " instead.") } } func removed(key string, message string) { if _, set := os.LookupEnv(key); set { - say("Configuration option '" + key + "' is no longer used.") - say(message) + say.Say("Configuration option '" + key + "' is no longer used.") + say.Say(message) } } func deprecated(key string, message string) { if _, set := os.LookupEnv(key); set { - say("Configuration option '" + key + "' is deprecated.") - say(message) + say.Say("Configuration option '" + key + "' is deprecated.") + say.Say(message) } } func experimental(key string) { if _, set := os.LookupEnv(key); set { - say("Configuration option '" + key + "' is experimental. Be prepared that this option will be removed!") + say.Say("Configuration option '" + key + "' is experimental. Be prepared that this option will be removed!") } } func config(c Configuration) { - say("MOB_CLI_NAME" + "=" + quote(c.CliName)) - say("MOB_REMOTE_NAME" + "=" + quote(c.RemoteName)) - say("MOB_WIP_COMMIT_MESSAGE" + "=" + quote(c.WipCommitMessage)) - say("MOB_GIT_HOOKS_ENABLED" + "=" + strconv.FormatBool(c.GitHooksEnabled)) - say("MOB_REQUIRE_COMMIT_MESSAGE" + "=" + strconv.FormatBool(c.RequireCommitMessage)) - say("MOB_VOICE_COMMAND" + "=" + quote(c.VoiceCommand)) - say("MOB_VOICE_MESSAGE" + "=" + quote(c.VoiceMessage)) - say("MOB_NOTIFY_COMMAND" + "=" + quote(c.NotifyCommand)) - say("MOB_NOTIFY_MESSAGE" + "=" + quote(c.NotifyMessage)) - say("MOB_NEXT_STAY" + "=" + strconv.FormatBool(c.NextStay)) - say("MOB_START_INCLUDE_UNCOMMITTED_CHANGES" + "=" + strconv.FormatBool(c.StartIncludeUncommittedChanges)) - say("MOB_STASH_NAME" + "=" + quote(c.StashName)) - say("MOB_WIP_BRANCH_QUALIFIER" + "=" + quote(c.WipBranchQualifier)) - say("MOB_WIP_BRANCH_QUALIFIER_SEPARATOR" + "=" + quote(c.WipBranchQualifierSeparator)) - say("MOB_WIP_BRANCH_PREFIX" + "=" + quote(c.WipBranchPrefix)) - say("MOB_DONE_SQUASH" + "=" + string(c.DoneSquash)) - say("MOB_OPEN_COMMAND" + "=" + quote(c.OpenCommand)) - say("MOB_TIMER" + "=" + quote(c.Timer)) - say("MOB_TIMER_ROOM" + "=" + quote(c.TimerRoom)) - say("MOB_TIMER_ROOM_USE_WIP_BRANCH_QUALIFIER" + "=" + strconv.FormatBool(c.TimerRoomUseWipBranchQualifier)) - say("MOB_TIMER_LOCAL" + "=" + strconv.FormatBool(c.TimerLocal)) - say("MOB_TIMER_USER" + "=" + quote(c.TimerUser)) - say("MOB_TIMER_URL" + "=" + quote(c.TimerUrl)) - say("MOB_TIMER_INSECURE" + "=" + strconv.FormatBool(c.TimerInsecure)) + say.Say("MOB_CLI_NAME" + "=" + quote(c.CliName)) + say.Say("MOB_REMOTE_NAME" + "=" + quote(c.RemoteName)) + say.Say("MOB_WIP_COMMIT_MESSAGE" + "=" + quote(c.WipCommitMessage)) + say.Say("MOB_GIT_HOOKS_ENABLED" + "=" + strconv.FormatBool(c.GitHooksEnabled)) + say.Say("MOB_REQUIRE_COMMIT_MESSAGE" + "=" + strconv.FormatBool(c.RequireCommitMessage)) + say.Say("MOB_VOICE_COMMAND" + "=" + quote(c.VoiceCommand)) + say.Say("MOB_VOICE_MESSAGE" + "=" + quote(c.VoiceMessage)) + say.Say("MOB_NOTIFY_COMMAND" + "=" + quote(c.NotifyCommand)) + say.Say("MOB_NOTIFY_MESSAGE" + "=" + quote(c.NotifyMessage)) + say.Say("MOB_NEXT_STAY" + "=" + strconv.FormatBool(c.NextStay)) + say.Say("MOB_START_INCLUDE_UNCOMMITTED_CHANGES" + "=" + strconv.FormatBool(c.StartIncludeUncommittedChanges)) + say.Say("MOB_STASH_NAME" + "=" + quote(c.StashName)) + say.Say("MOB_WIP_BRANCH_QUALIFIER" + "=" + quote(c.WipBranchQualifier)) + say.Say("MOB_WIP_BRANCH_QUALIFIER_SEPARATOR" + "=" + quote(c.WipBranchQualifierSeparator)) + say.Say("MOB_WIP_BRANCH_PREFIX" + "=" + quote(c.WipBranchPrefix)) + say.Say("MOB_DONE_SQUASH" + "=" + string(c.DoneSquash)) + say.Say("MOB_OPEN_COMMAND" + "=" + quote(c.OpenCommand)) + say.Say("MOB_TIMER" + "=" + quote(c.Timer)) + say.Say("MOB_TIMER_ROOM" + "=" + quote(c.TimerRoom)) + say.Say("MOB_TIMER_ROOM_USE_WIP_BRANCH_QUALIFIER" + "=" + strconv.FormatBool(c.TimerRoomUseWipBranchQualifier)) + say.Say("MOB_TIMER_LOCAL" + "=" + strconv.FormatBool(c.TimerLocal)) + say.Say("MOB_TIMER_USER" + "=" + quote(c.TimerUser)) + say.Say("MOB_TIMER_URL" + "=" + quote(c.TimerUrl)) + say.Say("MOB_TIMER_INSECURE" + "=" + strconv.FormatBool(c.TimerInsecure)) } func quote(value string) string { @@ -783,7 +773,7 @@ func execute(command string, parameter []string, configuration Configuration) { } else if configuration.Timer != "" { startTimer(configuration.Timer, configuration) } else { - sayInfo("It's now " + currentTime() + ". Happy collaborating! :)") + say.Info("It's now " + currentTime() + ". Happy collaborating! :)") } case "b", "branch": branch(configuration) @@ -852,7 +842,7 @@ func clean(configuration Configuration) { if currentBranch.isOrphanWipBranch(configuration) { currentBaseBranch, _ := determineBranches(currentBranch, localBranches, configuration) - sayInfo("Current branch " + currentBranch.Name + " is an orphan") + say.Info("Current branch " + currentBranch.Name + " is an orphan") if currentBaseBranch.exists(localBranches) { git("checkout", currentBaseBranch.Name) } else if newBranch("main").exists(localBranches) { @@ -865,7 +855,7 @@ func clean(configuration Configuration) { for _, branch := range localBranches { b := newBranch(branch) if b.isOrphanWipBranch(configuration) { - sayInfo("Removing orphan wip branch " + b.Name) + say.Info("Removing orphan wip branch " + b.Name) git("branch", "-D", b.Name) } } @@ -877,10 +867,10 @@ func (branch Branch) isOrphanWipBranch(configuration Configuration) bool { } func branch(configuration Configuration) { - say(silentgit("branch", "--list", "--remote", newBranch("*").addWipPrefix(configuration).remote(configuration).Name)) + say.Say(silentgit("branch", "--list", "--remote", newBranch("*").addWipPrefix(configuration).remote(configuration).Name)) // DEPRECATED - say(silentgit("branch", "--list", "--remote", newBranch("mob-session").remote(configuration).Name)) + say.Say(silentgit("branch", "--list", "--remote", newBranch("mob-session").remote(configuration).Name)) } func determineBranches(currentBranch Branch, localBranches []string, configuration Configuration) (baseBranch Branch, wipBranch Branch) { @@ -896,7 +886,7 @@ func determineBranches(currentBranch Branch, localBranches []string, configurati wipBranch = currentBranch.addWipPrefix(configuration).addWipQualifier(configuration) } - debugInfo("on currentBranch " + currentBranch.String() + " => BASE " + baseBranch.String() + " WIP " + wipBranch.String() + " with allLocalBranches " + strings.Join(localBranches, ",")) + say.Debug("on currentBranch " + currentBranch.String() + " => BASE " + baseBranch.String() + " WIP " + wipBranch.String() + " with allLocalBranches " + strings.Join(localBranches, ",")) if currentBranch != baseBranch && currentBranch != wipBranch { // this is unreachable code, but we keep it as a backup panic("assertion failed! neither on base nor on wip branch") @@ -911,7 +901,7 @@ func getSleepCommand(timeoutInSeconds int) string { func injectCommandWithMessage(command string, message string) string { placeHolders := strings.Count(command, "%s") if placeHolders > 1 { - sayError(fmt.Sprintf("Too many placeholders (%d) in format command string: %s", placeHolders, command)) + say.Error(fmt.Sprintf("Too many placeholders (%d) in format command string: %s", placeHolders, command)) exit(1) } if placeHolders == 0 { @@ -941,14 +931,14 @@ func executeCommandsInBackgroundProcess(commands ...string) (err error) { cmds = append(cmds, c) } } - debugInfo(fmt.Sprintf("Operating System %s", runtime.GOOS)) + say.Debug(fmt.Sprintf("Operating System %s", runtime.GOOS)) switch runtime.GOOS { case "windows": _, err = startCommand("powershell", "-command", fmt.Sprintf("start-process powershell -NoNewWindow -ArgumentList '-command \"%s\"'", strings.Join(cmds, ";"))) case "darwin", "linux": _, err = startCommand("sh", "-c", fmt.Sprintf("(%s) &", strings.Join(cmds, ";"))) default: - sayWarning(fmt.Sprintf("Cannot execute background commands on your os: %s", runtime.GOOS)) + say.Warning(fmt.Sprintf("Cannot execute background commands on your os: %s", runtime.GOOS)) } return err } @@ -958,14 +948,14 @@ func startTimer(timerInMinutes string, configuration Configuration) { timeoutInSeconds := timeoutInMinutes * 60 timeOfTimeout := time.Now().Add(time.Minute * time.Duration(timeoutInMinutes)).Format("15:04") - debugInfo(fmt.Sprintf("Starting timer at %s for %d minutes = %d seconds (parsed from user input %s)", timeOfTimeout, timeoutInMinutes, timeoutInSeconds, timerInMinutes)) + say.Debug(fmt.Sprintf("Starting timer at %s for %d minutes = %d seconds (parsed from user input %s)", timeOfTimeout, timeoutInMinutes, timeoutInSeconds, timerInMinutes)) room := getMobTimerRoom(configuration) startRemoteTimer := room != "" startLocalTimer := configuration.TimerLocal if !startRemoteTimer && !startLocalTimer { - sayError("No timer configured, not starting timer") + say.Error("No timer configured, not starting timer") exit(1) } @@ -973,8 +963,8 @@ func startTimer(timerInMinutes string, configuration Configuration) { timerUser := getUserForMobTimer(configuration.TimerUser) err := httpPutTimer(timeoutInMinutes, room, timerUser, configuration.TimerUrl, configuration.TimerInsecure) if err != nil { - sayError("remote timer couldn't be started") - sayError(err.Error()) + say.Error("remote timer couldn't be started") + say.Error(err.Error()) exit(1) } } @@ -983,18 +973,18 @@ func startTimer(timerInMinutes string, configuration Configuration) { err := executeCommandsInBackgroundProcess(getSleepCommand(timeoutInSeconds), getVoiceCommand(configuration.VoiceMessage, configuration.VoiceCommand), getNotifyCommand(configuration.NotifyMessage, configuration.NotifyCommand)) if err != nil { - sayError(fmt.Sprintf("timer couldn't be started on your system (%s)", runtime.GOOS)) - sayError(err.Error()) + say.Error(fmt.Sprintf("timer couldn't be started on your system (%s)", runtime.GOOS)) + say.Error(err.Error()) exit(1) } } - sayInfo("It's now " + currentTime() + ". " + fmt.Sprintf("%d min timer ends at approx. %s", timeoutInMinutes, timeOfTimeout) + ". Happy collaborating! :)") + say.Info("It's now " + currentTime() + ". " + fmt.Sprintf("%d min timer ends at approx. %s", timeoutInMinutes, timeOfTimeout) + ". Happy collaborating! :)") } func getMobTimerRoom(configuration Configuration) string { if !isGit() { - debugInfo("timer not in git repository, using MOB_TIMER_ROOM for room name") + say.Debug("timer not in git repository, using MOB_TIMER_ROOM for room name") return configuration.TimerRoom } @@ -1010,7 +1000,7 @@ func getMobTimerRoom(configuration Configuration) string { } if configuration.TimerRoomUseWipBranchQualifier && currentWipBranchQualifier != "" { - sayInfo("Using wip branch qualifier for room name") + say.Info("Using wip branch qualifier for room name") return currentWipBranchQualifier } @@ -1022,14 +1012,14 @@ func startBreakTimer(timerInMinutes string, configuration Configuration) { timeoutInSeconds := timeoutInMinutes * 60 timeOfTimeout := time.Now().Add(time.Minute * time.Duration(timeoutInMinutes)).Format("15:04") - debugInfo(fmt.Sprintf("Starting break timer at %s for %d minutes = %d seconds (parsed from user input %s)", timeOfTimeout, timeoutInMinutes, timeoutInSeconds, timerInMinutes)) + say.Debug(fmt.Sprintf("Starting break timer at %s for %d minutes = %d seconds (parsed from user input %s)", timeOfTimeout, timeoutInMinutes, timeoutInSeconds, timerInMinutes)) room := getMobTimerRoom(configuration) startRemoteTimer := room != "" startLocalTimer := configuration.TimerLocal if !startRemoteTimer && !startLocalTimer { - sayError("No break timer configured, not starting break timer") + say.Error("No break timer configured, not starting break timer") exit(1) } @@ -1038,8 +1028,8 @@ func startBreakTimer(timerInMinutes string, configuration Configuration) { err := httpPutBreakTimer(timeoutInMinutes, room, timerUser, configuration.TimerUrl, configuration.TimerInsecure) if err != nil { - sayError("remote break timer couldn't be started") - sayError(err.Error()) + say.Error("remote break timer couldn't be started") + say.Error(err.Error()) exit(1) } } @@ -1048,13 +1038,13 @@ func startBreakTimer(timerInMinutes string, configuration Configuration) { err := executeCommandsInBackgroundProcess(getSleepCommand(timeoutInSeconds), getVoiceCommand("mob start", configuration.VoiceCommand), getNotifyCommand("mob start", configuration.NotifyCommand)) if err != nil { - sayError(fmt.Sprintf("break timer couldn't be started on your system (%s)", runtime.GOOS)) - sayError(err.Error()) + say.Error(fmt.Sprintf("break timer couldn't be started on your system (%s)", runtime.GOOS)) + say.Error(err.Error()) exit(1) } } - sayInfo("It's now " + currentTime() + ". " + fmt.Sprintf("%d min break timer ends at approx. %s", timeoutInMinutes, timeOfTimeout) + ". Happy collaborating! :)") + say.Info("It's now " + currentTime() + ". " + fmt.Sprintf("%d min break timer ends at approx. %s", timeoutInMinutes, timeOfTimeout) + ". Happy collaborating! :)") } func getUserForMobTimer(userOverride string) string { @@ -1089,7 +1079,7 @@ func httpPutBreakTimer(timeoutInMinutes int, room string, user string, timerServ } func sendRequest(requestBody []byte, requestMethod string, requestUrl string, disableSSLVerification bool) error { - sayInfo(requestMethod + " " + requestUrl + " " + string(requestBody)) + say.Info(requestMethod + " " + requestUrl + " " + string(requestBody)) responseBody := bytes.NewBuffer(requestBody) request, requestCreationError := http.NewRequest(requestMethod, requestUrl, responseBody) @@ -1111,8 +1101,8 @@ func sendRequest(requestBody []byte, requestMethod string, requestUrl string, di if e, ok := responseErr.(*url.Error); ok { switch e.Err.(type) { case x509.UnknownAuthorityError: - sayError("The timer.mob.sh SSL certificate is signed by an unknown authority!") - sayFix("HINT: You can ignore that by adding MOB_TIMER_INSECURE=true to your configuration or environment.", + say.Error("The timer.mob.sh SSL certificate is signed by an unknown authority!") + say.Fix("HINT: You can ignore that by adding MOB_TIMER_INSECURE=true to your configuration or environment.", "echo MOB_TIMER_INSECURE=true >> ~/.mob") return fmt.Errorf("failed, to amke the http request: %w", responseErr) @@ -1131,7 +1121,7 @@ func sendRequest(requestBody []byte, requestMethod string, requestUrl string, di return fmt.Errorf("failed to read the http response: %w", responseReadingErr) } if string(body) != "" { - sayInfo(string(body)) + say.Info(string(body)) } return nil } @@ -1145,19 +1135,19 @@ func moo(configuration Configuration) { err := executeCommandsInBackgroundProcess(getVoiceCommand(voiceMessage, configuration.VoiceCommand)) if err != nil { - sayWarning(fmt.Sprintf("can't run voice command on your system (%s)", runtime.GOOS)) - sayWarning(err.Error()) + say.Warning(fmt.Sprintf("can't run voice command on your system (%s)", runtime.GOOS)) + say.Warning(err.Error()) return } - sayInfo(voiceMessage) + say.Info(voiceMessage) } func reset(configuration Configuration) { if configuration.ResetDeleteRemoteWipBranch { deleteRemoteWipBranch(configuration) } else { - sayFix("Executing this command deletes the mob branch for everyone. If you're sure you want that, use", configuration.mob("reset --delete-remote-wip-branch")) + say.Fix("Executing this command deletes the mob branch for everyone. If you're sure you want that, use", configuration.mob("reset --delete-remote-wip-branch")) } } @@ -1173,19 +1163,19 @@ func deleteRemoteWipBranch(configuration Configuration) { if currentWipBranch.hasRemoteBranch(configuration) { gitWithoutEmptyStrings("push", configuration.gitHooksOption(), configuration.RemoteName, "--delete", currentWipBranch.String()) } - sayInfo("Branches " + currentWipBranch.String() + " and " + currentWipBranch.remote(configuration).String() + " deleted") + say.Info("Branches " + currentWipBranch.String() + " and " + currentWipBranch.remote(configuration).String() + " deleted") } func start(configuration Configuration) error { uncommittedChanges := hasUncommittedChanges() if uncommittedChanges && !configuration.StartIncludeUncommittedChanges { - sayInfo("cannot start; clean working tree required") + say.Info("cannot start; clean working tree required") sayUnstagedChangesInfo() sayUntrackedFilesInfo() if configuration.StartCreate { - sayFix("To start, including uncommitted changes and create the remote branch, use", configuration.mob("start --create --include-uncommitted-changes")) + say.Fix("To start, including uncommitted changes and create the remote branch, use", configuration.mob("start --create --include-uncommitted-changes")) } else { - sayFix("To start, including uncommitted changes, use", configuration.mob("start --include-uncommitted-changes")) + say.Fix("To start, including uncommitted changes, use", configuration.mob("start --include-uncommitted-changes")) } return errors.New("cannot start; clean working tree required") } @@ -1194,28 +1184,28 @@ func start(configuration Configuration) error { currentBaseBranch, currentWipBranch := determineBranches(gitCurrentBranch(), gitBranches(), configuration) if !currentBaseBranch.hasRemoteBranch(configuration) && !configuration.StartCreate { - sayError("Remote branch " + currentBaseBranch.remote(configuration).String() + " is missing") - sayFix("To start and and create the remote branch", "mob start --create") + say.Error("Remote branch " + currentBaseBranch.remote(configuration).String() + " is missing") + say.Fix("To start and and create the remote branch", "mob start --create") return errors.New("remote branch is missing") } createRemoteBranch(configuration, currentBaseBranch) if currentBaseBranch.hasUnpushedCommits(configuration) { - sayError("cannot start; unpushed changes on base branch must be pushed upstream") - sayFix("to fix this, push those commits and try again", "git push "+configuration.RemoteName+" "+currentBaseBranch.String()) + say.Error("cannot start; unpushed changes on base branch must be pushed upstream") + say.Fix("to fix this, push those commits and try again", "git push "+configuration.RemoteName+" "+currentBaseBranch.String()) return errors.New("cannot start; unpushed changes on base branch must be pushed upstream") } if uncommittedChanges && silentgit("ls-tree", "-r", "HEAD", "--full-name", "--name-only", ".") == "" { - sayError("cannot start; current working dir is an uncommitted subdir") - sayFix("to fix this, go to the parent directory and try again", "cd ..") + say.Error("cannot start; current working dir is an uncommitted subdir") + say.Fix("to fix this, go to the parent directory and try again", "cd ..") return errors.New("cannot start; current working dir is an uncommitted subdir") } if uncommittedChanges { git("stash", "push", "--include-untracked", "--message", configuration.StashName) - sayInfo("uncommitted changes were stashed. If an error occurs later on, you can recover them with 'git stash pop'.") + say.Info("uncommitted changes were stashed. If an error occurs later on, you can recover them with 'git stash pop'.") } if !isMobProgramming(configuration) { @@ -1236,7 +1226,7 @@ func start(configuration Configuration) error { git("stash", "pop", stash) } - sayInfo("you are on wip branch '" + currentWipBranch.String() + "' (base branch '" + currentBaseBranch.String() + "')") + say.Info("you are on wip branch '" + currentWipBranch.String() + "' (base branch '" + currentBaseBranch.String() + "')") sayLastCommitsList(currentBaseBranch.String(), currentWipBranch.String()) openLastModifiedFileIfPresent(configuration) @@ -1248,45 +1238,45 @@ func createRemoteBranch(configuration Configuration, currentBaseBranch Branch) { if !currentBaseBranch.hasRemoteBranch(configuration) && configuration.StartCreate { git("push", configuration.RemoteName, currentBaseBranch.String(), "--set-upstream") } else if currentBaseBranch.hasRemoteBranch(configuration) && configuration.StartCreate { - sayInfo("Remote branch " + currentBaseBranch.remote(configuration).String() + " already exists") + say.Info("Remote branch " + currentBaseBranch.remote(configuration).String() + " already exists") } } func openLastModifiedFileIfPresent(configuration Configuration) { if !configuration.isOpenCommandGiven() { - debugInfo("No open command given") + say.Debug("No open command given") return } - debugInfo("Try to open last modified file") + say.Debug("Try to open last modified file") if !lastCommitIsWipCommit(configuration) { - debugInfo("Last commit isn't a WIP commit.") + say.Debug("Last commit isn't a WIP commit.") return } lastCommitMessage := lastCommitMessage() split := strings.Split(lastCommitMessage, "lastFile:") if len(split) == 1 { - sayWarning("Couldn't find last modified file in commit message!") + say.Warning("Couldn't find last modified file in commit message!") return } if len(split) > 2 { - sayWarning("Could not determine last modified file from commit message, separator was used multiple times!") + say.Warning("Could not determine last modified file from commit message, separator was used multiple times!") return } lastModifiedFile := split[1] if lastModifiedFile == "" { - debugInfo("Could not find last modified file in commit message") + say.Debug("Could not find last modified file in commit message") return } lastModifiedFilePath := gitRootDir() + "/" + lastModifiedFile commandname, args := configuration.openCommandFor(lastModifiedFilePath) _, err := startCommand(commandname, args...) if err != nil { - sayWarning(fmt.Sprintf("Couldn't open last modified file on your system (%s)", runtime.GOOS)) - sayWarning(err.Error()) + say.Warning(fmt.Sprintf("Couldn't open last modified file on your system (%s)", runtime.GOOS)) + say.Warning(err.Error()) return } - debugInfo("Open last modified file: " + lastModifiedFilePath) + say.Debug("Open last modified file: " + lastModifiedFilePath) } func warnForActiveWipBranches(configuration Configuration, currentBaseBranch Branch) { @@ -1297,9 +1287,9 @@ func warnForActiveWipBranches(configuration Configuration, currentBaseBranch Bra // TODO show all active wip branches, even non-qualified ones existingWipBranches := getWipBranchesForBaseBranch(currentBaseBranch, configuration) if len(existingWipBranches) > 0 && configuration.WipBranchQualifier == "" { - sayWarning("Creating a new wip branch even though preexisting wip branches have been detected.") + say.Warning("Creating a new wip branch even though preexisting wip branches have been detected.") for _, wipBranch := range existingWipBranches { - sayWithPrefix(wipBranch, " - ") + say.WithPrefix(wipBranch, " - ") } } } @@ -1307,9 +1297,9 @@ func warnForActiveWipBranches(configuration Configuration, currentBaseBranch Bra func showActiveMobSessions(configuration Configuration, currentBaseBranch Branch) { existingWipBranches := getWipBranchesForBaseBranch(currentBaseBranch, configuration) if len(existingWipBranches) > 0 { - sayInfo("remote wip branches detected:") + say.Info("remote wip branches detected:") for _, wipBranch := range existingWipBranches { - sayWithPrefix(wipBranch, " - ") + say.WithPrefix(wipBranch, " - ") } } } @@ -1318,8 +1308,8 @@ func sayUntrackedFilesInfo() { untrackedFiles := getUntrackedFiles() hasUntrackedFiles := len(untrackedFiles) > 0 if hasUntrackedFiles { - sayInfo("untracked files present:") - sayInfoIndented(untrackedFiles) + say.Info("untracked files present:") + say.InfoIndented(untrackedFiles) } } @@ -1327,14 +1317,14 @@ func sayUnstagedChangesInfo() { unstagedChanges := getUnstagedChanges() hasUnstagedChanges := len(unstagedChanges) > 0 if hasUnstagedChanges { - sayInfo("unstaged changes present:") - sayInfoIndented(unstagedChanges) + say.Info("unstaged changes present:") + say.InfoIndented(unstagedChanges) } } func getWipBranchesForBaseBranch(currentBaseBranch Branch, configuration Configuration) []string { remoteBranches := gitRemoteBranches() - debugInfo("check on current base branch " + currentBaseBranch.String() + " with remote branches " + strings.Join(remoteBranches, ",")) + say.Debug("check on current base branch " + currentBaseBranch.String() + " with remote branches " + strings.Join(remoteBranches, ",")) remoteBranchWithQualifier := currentBaseBranch.addWipPrefix(configuration).addWipQualifier(configuration).remote(configuration).Name remoteBranchNoQualifier := currentBaseBranch.addWipPrefix(configuration).remote(configuration).Name @@ -1356,9 +1346,9 @@ func getWipBranchesForBaseBranch(currentBaseBranch Branch, configuration Configu func startJoinMobSession(configuration Configuration) { baseBranch, currentWipBranch := determineBranches(gitCurrentBranch(), gitBranches(), configuration) - sayInfo("joining existing session from " + currentWipBranch.remote(configuration).String()) + say.Info("joining existing session from " + currentWipBranch.remote(configuration).String()) if doBranchesDiverge(baseBranch.remote(configuration).Name, currentWipBranch.Name) { - sayWarning("Careful, your wip branch (" + currentWipBranch.Name + ") diverges from your main branch (" + baseBranch.remote(configuration).Name + ") !") + say.Warning("Careful, your wip branch (" + currentWipBranch.Name + ") diverges from your main branch (" + baseBranch.remote(configuration).Name + ") !") } git("checkout", "-B", currentWipBranch.Name, currentWipBranch.remote(configuration).Name) @@ -1368,7 +1358,7 @@ func startJoinMobSession(configuration Configuration) { func startNewMobSession(configuration Configuration) { currentBaseBranch, currentWipBranch := determineBranches(gitCurrentBranch(), gitBranches(), configuration) - sayInfo("starting new session from " + currentBaseBranch.remote(configuration).String()) + say.Info("starting new session from " + currentBaseBranch.remote(configuration).String()) git("checkout", "-B", currentWipBranch.Name, currentBaseBranch.remote(configuration).Name) gitWithoutEmptyStrings("push", configuration.gitHooksOption(), "--set-upstream", configuration.RemoteName, currentWipBranch.Name) } @@ -1394,12 +1384,12 @@ func findStashByName(stashes string, stash string) string { func next(configuration Configuration) { if !isMobProgramming(configuration) { - sayFix("to start working together, use", configuration.mob("start")) + say.Fix("to start working together, use", configuration.mob("start")) return } if !configuration.hasCustomCommitMessage() && configuration.RequireCommitMessage && hasUncommittedChanges() { - sayError("commit message required") + say.Error("commit message required") return } @@ -1409,7 +1399,7 @@ func next(configuration Configuration) { if currentWipBranch.hasLocalCommits(configuration) { gitWithoutEmptyStrings("push", configuration.gitHooksOption(), configuration.RemoteName, currentWipBranch.Name) } else { - sayInfo("nothing was done, so nothing to commit") + say.Info("nothing was done, so nothing to commit") } } else { makeWipCommit(configuration) @@ -1434,8 +1424,8 @@ func makeWipCommit(configuration Configuration) { git("add", "--all") commitMessage := createWipCommitMessage(configuration) gitWithoutEmptyStrings("commit", "--message", commitMessage, configuration.gitHooksOption()) - sayInfoIndented(getChangesOfLastCommit()) - sayInfoIndented(gitCommitHash()) + say.InfoIndented(getChangesOfLastCommit()) + say.InfoIndented(gitCommitHash()) } func createWipCommitMessage(configuration Configuration) string { @@ -1456,20 +1446,20 @@ func getPathOfLastModifiedFile() string { lastModifiedFilePath := "" lastModifiedTime := time.Time{} - debugInfo("Find last modified file") + say.Debug("Find last modified file") if len(files) == 1 { lastModifiedFilePath = files[0] - debugInfo("Just one modified file: " + lastModifiedFilePath) + say.Debug("Just one modified file: " + lastModifiedFilePath) return lastModifiedFilePath } for _, file := range files { absoluteFilepath := rootDir + "/" + file - debugInfo(absoluteFilepath) + say.Debug(absoluteFilepath) info, err := os.Stat(absoluteFilepath) if err != nil { - sayWarning("Could not get statistics of file: " + absoluteFilepath) - sayWarning(err.Error()) + say.Warning("Could not get statistics of file: " + absoluteFilepath) + say.Warning(err.Error()) continue } modTime := info.ModTime() @@ -1477,14 +1467,14 @@ func getPathOfLastModifiedFile() string { lastModifiedTime = modTime lastModifiedFilePath = file } - debugInfo(modTime.String()) + say.Debug(modTime.String()) } return lastModifiedFilePath } // uses git status --short. To work properly files have to be staged. func getModifiedFiles(rootDir string) []string { - debugInfo("Find modified files") + say.Debug("Find modified files") oldWorkingDir := workingDir workingDir = rootDir gitstatus := silentgit("status", "--short") @@ -1501,7 +1491,7 @@ func getModifiedFiles(rootDir string) []string { continue } relativeFilepath = strings.TrimSpace(relativeFilepath) - debugInfo(relativeFilepath) + say.Debug(relativeFilepath) files = append(files, relativeFilepath) } return files @@ -1521,7 +1511,7 @@ func fetch(configuration Configuration) { func done(configuration Configuration) { if !isMobProgramming(configuration) { - sayFix("to start working together, use", configuration.mob("start")) + say.Fix("to start working together, use", configuration.mob("start")) return } @@ -1545,8 +1535,8 @@ func done(configuration Configuration) { if mergeFailed != nil { // TODO should this be an error and a fix for that error? - sayWarning("Skipped deleting " + wipBranch.Name + " because of merge conflicts.") - sayWarning("To fix this, solve the merge conflict manually, commit, push, and afterwards delete " + wipBranch.Name) + say.Warning("Skipped deleting " + wipBranch.Name + " because of merge conflicts.") + say.Warning("To fix this, solve the merge conflict manually, commit, push, and afterwards delete " + wipBranch.Name) return } @@ -1561,23 +1551,23 @@ func done(configuration Configuration) { cachedChanges := getCachedChanges() hasCachedChanges := len(cachedChanges) > 0 if hasCachedChanges { - sayInfoIndented(cachedChanges) + say.InfoIndented(cachedChanges) } err := appendCoauthorsToSquashMsg(gitDir()) if err != nil { - sayWarning(err.Error()) + say.Warning(err.Error()) } if hasUncommittedChanges() { - sayNext("To finish, use", "git commit") + say.Next("To finish, use", "git commit") } else if configuration.DoneSquash == Squash { - sayInfo("nothing was done, so nothing to commit") + say.Info("nothing was done, so nothing to commit") } } else { git("checkout", baseBranch.Name) git("branch", "-D", wipBranch.Name) - sayInfo("someone else already ended your session") + say.Info("someone else already ended your session") } } @@ -1600,12 +1590,12 @@ func squashOrCommit(configuration Configuration) string { func status(configuration Configuration) { if isMobProgramming(configuration) { currentBaseBranch, currentWipBranch := determineBranches(gitCurrentBranch(), gitBranches(), configuration) - sayInfo("you are on wip branch " + currentWipBranch.String() + " (base branch " + currentBaseBranch.String() + ")") + say.Info("you are on wip branch " + currentWipBranch.String() + " (base branch " + currentBaseBranch.String() + ")") sayLastCommitsList(currentBaseBranch.String(), currentWipBranch.String()) } else { currentBaseBranch, _ := determineBranches(gitCurrentBranch(), gitBranches(), configuration) - sayInfo("you are on base branch '" + currentBaseBranch.String() + "'") + say.Info("you are on base branch '" + currentBaseBranch.String() + "'") showActiveMobSessions(configuration, currentBaseBranch) } } @@ -1615,12 +1605,12 @@ func sayLastCommitsList(currentBaseBranch string, currentWipBranch string) { log := silentgit("--no-pager", "log", commitsBaseWipBranch, "--pretty=format:%h %cr <%an>", "--abbrev-commit") lines := strings.Split(log, "\n") if len(lines) > 5 { - sayInfo("wip branch '" + currentWipBranch + "' contains " + strconv.Itoa(len(lines)) + " commits. The last 5 were:") + say.Info("wip branch '" + currentWipBranch + "' contains " + strconv.Itoa(len(lines)) + " commits. The last 5 were:") lines = lines[:5] } ReverseSlice(lines) output := strings.Join(lines, "\n") - say(output) + say.Say(output) } func ReverseSlice(s interface{}) { @@ -1643,14 +1633,14 @@ func hasUncommittedChanges() bool { func isMobProgramming(configuration Configuration) bool { currentBranch := gitCurrentBranch() _, currentWipBranch := determineBranches(currentBranch, gitBranches(), configuration) - debugInfo("current branch " + currentBranch.String() + " and currentWipBranch " + currentWipBranch.String()) + say.Debug("current branch " + currentBranch.String() + " and currentWipBranch " + currentWipBranch.String()) return currentWipBranch == currentBranch } func hasLocalBranch(localBranch string) bool { localBranches := gitBranches() - debugInfo("Local Branches: " + strings.Join(localBranches, "\n")) - debugInfo("Local Branch: " + localBranch) + say.Debug("Local Branches: " + strings.Join(localBranches, "\n")) + say.Debug("Local Branch: " + localBranch) for i := 0; i < len(localBranches); i++ { if localBranches[i] == localBranch { @@ -1691,11 +1681,11 @@ func gitUserEmail() string { } func showNext(configuration Configuration) { - debugInfo("determining next person based on previous changes") + say.Debug("determining next person based on previous changes") gitUserName := gitUserName() if gitUserName == "" { - sayWarning("failed to detect who's next because you haven't set your git user name") - sayFix("To fix, use", "git config --global user.name \"Your Name Here\"") + say.Warning("failed to detect who's next because you haven't set your git user name") + say.Fix("To fix, use", "git config --global user.name \"Your Name Here\"") return } @@ -1705,17 +1695,17 @@ func showNext(configuration Configuration) { changes := silentgit("--no-pager", "log", commitsBaseWipBranch, "--pretty=format:%an", "--abbrev-commit") lines := strings.Split(strings.Replace(changes, "\r\n", "\n", -1), "\n") numberOfLines := len(lines) - debugInfo("there have been " + strconv.Itoa(numberOfLines) + " changes") - debugInfo("current git user.name is '" + gitUserName + "'") + say.Debug("there have been " + strconv.Itoa(numberOfLines) + " changes") + say.Debug("current git user.name is '" + gitUserName + "'") if numberOfLines < 1 { return } nextTypist, previousCommitters := findNextTypist(lines, gitUserName) if nextTypist != "" { if len(previousCommitters) != 0 { - sayInfo("Committers after your last commit: " + strings.Join(previousCommitters, ", ")) + say.Info("Committers after your last commit: " + strings.Join(previousCommitters, ", ")) } - sayInfo("***" + nextTypist + "*** is (probably) next.") + say.Info("***" + nextTypist + "*** is (probably) next.") } } @@ -1770,11 +1760,11 @@ Other Add '--debug' to any option to enable verbose logging. ` - say(output) + say.Say(output) } func version() { - say("v" + versionNumber) + say.Say("v" + versionNumber) } func silentgit(args ...string) string { @@ -1782,11 +1772,11 @@ func silentgit(args ...string) string { if err != nil { if !isGit() { - sayError("expecting the current working directory to be a git repository.") + say.Error("expecting the current working directory to be a git repository.") } else { - sayError(commandString) - sayError(output) - sayError(err.Error()) + say.Error(commandString) + say.Error(output) + say.Error(err.Error()) } exit(1) } @@ -1827,15 +1817,15 @@ func git(args ...string) { if err != nil { if !isGit() { - sayError("expecting the current working directory to be a git repository.") + say.Error("expecting the current working directory to be a git repository.") } else { - sayError(commandString) - sayError(output) - sayError(err.Error()) + say.Error(commandString) + say.Error(output) + say.Error(err.Error()) } exit(1) } else { - sayIndented(commandString) + say.Indented(commandString) } } @@ -1847,21 +1837,21 @@ func gitignorefailure(args ...string) error { commandString, output, err = runCommandSilent("git", args...) } - sayIndented(commandString) + say.Indented(commandString) if err != nil { if !isGit() { - sayError("expecting the current working directory to be a git repository.") + say.Error("expecting the current working directory to be a git repository.") exit(1) } else { - sayWarning(commandString) - sayWarning(output) - sayWarning(err.Error()) + say.Warning(commandString) + say.Warning(output) + say.Warning(err.Error()) return err } } - sayIndented(commandString) + say.Indented(commandString) return nil } @@ -1872,7 +1862,7 @@ func gitCommitHash() string { func isGitInstalled() bool { _, _, err := runCommandSilent("git", "--version") if err != nil { - debugInfo("isGitInstalled encountered an error: " + err.Error()) + say.Debug("isGitInstalled encountered an error: " + err.Error()) } return err == nil } @@ -1888,10 +1878,10 @@ func runCommandSilent(name string, args ...string) (string, string, error) { command.Dir = workingDir } commandString := strings.Join(command.Args, " ") - debugInfo("Running command <" + commandString + "> in silent mode, capturing combined output") + say.Debug("Running command <" + commandString + "> in silent mode, capturing combined output") outputBytes, err := command.CombinedOutput() output := string(outputBytes) - debugInfo(output) + say.Debug(output) return commandString, output, err } @@ -1901,7 +1891,7 @@ func runCommand(name string, args ...string) (string, string, error) { command.Dir = workingDir } commandString := strings.Join(command.Args, " ") - debugInfo("Running command <" + commandString + "> passing output through") + say.Debug("Running command <" + commandString + "> passing output through") stdout, _ := command.StdoutPipe() command.Stderr = command.Stdout @@ -1921,21 +1911,21 @@ func runCommand(name string, args ...string) (string, string, error) { lineEnded = true } else { if lineEnded { - printToConsole(" ") + say.PrintToConsole(" ") lineEnded = false } } - printToConsole(character) + say.PrintToConsole(character) output += character } errWait := command.Wait() if errWait != nil { - debugInfo(output) + say.Debug(output) return commandString, output, errWait } - debugInfo(output) + say.Debug(output) return commandString, output, nil } @@ -1945,7 +1935,7 @@ func startCommand(name string, args ...string) (string, error) { command.Dir = workingDir } commandString := strings.Join(command.Args, " ") - debugInfo("Starting command " + commandString) + say.Debug("Starting command " + commandString) err := command.Start() return commandString, err } @@ -1953,65 +1943,3 @@ func startCommand(name string, args ...string) (string, error) { var exit = func(code int) { os.Exit(code) } - -func sayError(text string) { - sayWithPrefix(text, "ERROR ") -} - -func debugInfo(text string) { - if Debug { - sayWithPrefix(text, "DEBUG ") - } -} - -func sayIndented(text string) { - sayWithPrefix(text, " ") -} - -func sayFix(instruction string, command string) { - sayWithPrefix(instruction, "👉 ") - sayEmptyLine() - sayIndented(command) - sayEmptyLine() -} - -func sayNext(instruction string, command string) { - sayWithPrefix(instruction, "👉 ") - sayEmptyLine() - sayIndented(command) - sayEmptyLine() -} - -func sayInfo(text string) { - sayWithPrefix(text, "> ") -} - -func sayInfoIndented(text string) { - sayWithPrefix(text, " ") -} - -func sayWarning(text string) { - sayWithPrefix(text, "⚠ ") -} - -func sayWithPrefix(s string, prefix string) { - lines := strings.Split(strings.TrimSpace(s), "\n") - for i := 0; i < len(lines); i++ { - printToConsole(prefix + strings.TrimSpace(lines[i]) + "\n") - } -} - -func say(s string) { - if len(s) == 0 { - return - } - printToConsole(strings.TrimRight(s, " \r\n\t\v\f") + "\n") -} - -func sayEmptyLine() { - printToConsole("\n") -} - -var printToConsole = func(message string) { - fmt.Print(message) -} diff --git a/mob_test.go b/mob_test.go index 0675116c..95690cc7 100644 --- a/mob_test.go +++ b/mob_test.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "github.com/remotemobprogramming/mob/v3/say" "io/ioutil" "os" "path/filepath" @@ -341,7 +342,7 @@ func TestExecuteKicksOffStatus(t *testing.T) { } func TestReadConfigurationFromFileOverrideEverything(t *testing.T) { - Debug = true + say.TurnOnDebugging() tempDir = t.TempDir() setWorkingDir(tempDir) @@ -401,7 +402,7 @@ func TestReadConfigurationFromFileOverrideEverything(t *testing.T) { } func TestReadConfigurationFromFileWithNonBooleanQuotedDoneSquashValue(t *testing.T) { - Debug = true + say.TurnOnDebugging() tempDir = t.TempDir() setWorkingDir(tempDir) @@ -411,7 +412,7 @@ func TestReadConfigurationFromFileWithNonBooleanQuotedDoneSquashValue(t *testing } func TestReadConfigurationFromFileAndSkipBrokenLines(t *testing.T) { - Debug = true + say.TurnOnDebugging() tempDir = t.TempDir() setWorkingDir(tempDir) @@ -421,7 +422,7 @@ func TestReadConfigurationFromFileAndSkipBrokenLines(t *testing.T) { } func TestSkipIfConfigurationDoesNotExist(t *testing.T) { - Debug = true + say.TurnOnDebugging() tempDir = t.TempDir() setWorkingDir(tempDir) @@ -726,7 +727,7 @@ func TestStartIncludeUnstagedChanges(t *testing.T) { func TestStartIncludeUnstagedChangesInNewWorkingDirectory(t *testing.T) { output, configuration := setup(t) configuration.StartIncludeUncommittedChanges = true - Debug = true + say.TurnOnDebugging() createDirectory(t, "subdirnew") setWorkingDir(tempDir + "/local/subdirnew") createFile(t, "test.txt", "contentIrrelevant") @@ -1115,7 +1116,7 @@ func TestStartDoneSquashWithUnpushedCommit(t *testing.T) { } func TestStartDoneSquashWipWithUnpushedCommit(t *testing.T) { - Debug = true + say.TurnOnDebugging() _, configuration := setup(t) configuration.DoneSquash = SquashWip @@ -1815,7 +1816,7 @@ func setup(t *testing.T) (output *string, configuration Configuration) { func captureOutput(t *testing.T) *string { messages := "" - printToConsole = func(text string) { + say.PrintToConsole = func(text string) { t.Log(strings.TrimRight(text, "\n")) messages += text } @@ -1837,7 +1838,7 @@ func createTestbed(t *testing.T, configuration Configuration) { workingDir = "" tempDir = t.TempDir() - say("Creating testbed in temporary directory " + tempDir) + say.Say("Creating testbed in temporary directory " + tempDir) run(t, "./create-testbed", tempDir) @@ -1848,7 +1849,7 @@ func createTestbed(t *testing.T, configuration Configuration) { func setWorkingDir(dir string) { workingDir = dir - say("\n===== cd " + dir) + say.Say("\n===== cd " + dir) } func assertCommits(t *testing.T, commits int) { diff --git a/say/say.go b/say/say.go new file mode 100644 index 00000000..197a4e9e --- /dev/null +++ b/say/say.go @@ -0,0 +1,84 @@ +package say + +import ( + "fmt" + "strings" +) + +var isDebug = false // override with --debug parameter + +func TurnOnDebugging() { + isDebug = true +} + +func TurnOnDebuggingByArgs(args []string) { + // debug needs to be parsed at the beginning to have DEBUG enabled as quickly as possible + // otherwise, parsing others or other parameters don't have debug enabled + for i := 0; i < len(args); i++ { + if args[i] == "--debug" { + isDebug = true + } + } +} + +func Error(text string) { + WithPrefix(text, "ERROR ") +} + +func Warning(text string) { + WithPrefix(text, "⚠ ") +} + +func Info(text string) { + WithPrefix(text, "> ") +} + +func InfoIndented(text string) { + WithPrefix(text, " ") +} + +func Indented(text string) { + WithPrefix(text, " ") +} + +func Fix(instruction string, command string) { + WithPrefix(instruction, "👉 ") + emptyLine() + Indented(command) + emptyLine() +} + +func Next(instruction string, command string) { + WithPrefix(instruction, "👉 ") + emptyLine() + Indented(command) + emptyLine() +} + +func WithPrefix(s string, prefix string) { + lines := strings.Split(strings.TrimSpace(s), "\n") + for i := 0; i < len(lines); i++ { + PrintToConsole(prefix + strings.TrimSpace(lines[i]) + "\n") + } +} + +func emptyLine() { + PrintToConsole("\n") +} + +func Say(s string) { + if len(s) == 0 { + return + } + PrintToConsole(strings.TrimRight(s, " \r\n\t\v\f") + "\n") +} + +func Debug(text string) { + if isDebug { + WithPrefix(text, "DEBUG ") + } +} + +var PrintToConsole = func(message string) { + fmt.Print(message) +} diff --git a/squash_wip.go b/squash_wip.go index e0812830..f5f2fbfb 100644 --- a/squash_wip.go +++ b/squash_wip.go @@ -1,6 +1,7 @@ package main import ( + "github.com/remotemobprogramming/mob/v3/say" "io" "io/ioutil" "os" @@ -22,13 +23,13 @@ func squashWip(configuration Configuration) { mobExecutable()+" squash-wip --git-editor", mobExecutable()+" squash-wip --git-sequence-editor", ) - sayInfo("rewriting history of '" + currentWipBranch.String() + "': squashing wip commits while keeping manual commits.") + say.Info("rewriting history of '" + currentWipBranch.String() + "': squashing wip commits while keeping manual commits.") git("rebase", "--interactive", "--keep-empty", mergeBase) setEnvGitEditor(originalGitEditor, originalGitSequenceEditor) - sayInfo("resulting history is:") + say.Info("resulting history is:") sayLastCommitsWithMessage(currentBaseBranch.remote(configuration).String(), currentWipBranch.String()) if lastCommitIsWipCommit(configuration) { // last commit is wip commit - sayInfo("undoing the final wip commit and staging its changes:") + say.Info("undoing the final wip commit and staging its changes:") git("reset", "--soft", "HEAD^") } @@ -48,11 +49,11 @@ func sayLastCommitsWithMessage(currentBaseBranch string, currentWipBranch string log := silentgit("--no-pager", "log", commitsBaseWipBranch, "--pretty=oneline", "--abbrev-commit") lines := strings.Split(log, "\n") if len(lines) > 10 { - sayInfo("wip branch '" + currentWipBranch + "' contains " + strconv.Itoa(len(lines)) + " commits. The last 10 were:") + say.Info("wip branch '" + currentWipBranch + "' contains " + strconv.Itoa(len(lines)) + " commits. The last 10 were:") lines = lines[:10] } output := strings.Join(lines, "\n") - say(output) + say.Say(output) } func setEnvGitEditor(gitEditor string, gitSequenceEditor string) { @@ -69,7 +70,7 @@ func getEnvGitEditor() (gitEditor string, gitSequenceEditor string) { func mobExecutable() string { if isTestEnvironment() { wd, _ := os.Getwd() - return "go run $(ls -1 " + wd + "/*.go | grep -v _test.go)" + return "cd " + wd + " && go run $(ls -1 ./*.go | grep -v _test.go)" } else { return "mob" }