diff --git a/cmd/control/cmd/root.go b/cmd/control/cmd/root.go index 518e1b2..60e1fe1 100644 --- a/cmd/control/cmd/root.go +++ b/cmd/control/cmd/root.go @@ -2,12 +2,22 @@ package cmd import ( "fmt" + "log" + "os/user" + "path/filepath" + "github.com/BurntSushi/toml" "github.com/curusarn/resh/cmd/control/status" + "github.com/curusarn/resh/pkg/cfg" "github.com/spf13/cobra" ) +// globals var exitCode status.Code +var version string +var commit string +var debug = false +var config cfg.Config var rootCmd = &cobra.Command{ Use: "reshctl", @@ -15,7 +25,22 @@ var rootCmd = &cobra.Command{ } // Execute reshctl -func Execute() status.Code { +func Execute(ver, com string) status.Code { + version = ver + commit = com + + usr, _ := user.Current() + dir := usr.HomeDir + configPath := filepath.Join(dir, ".config/resh.toml") + if _, err := toml.DecodeFile(configPath, &config); err != nil { + log.Println("Error reading config", err) + return status.Fail + } + if config.Debug { + debug = true + // log.SetFlags(log.LstdFlags | log.Lmicroseconds) + } + rootCmd.AddCommand(disableCmd) disableCmd.AddCommand(disableArrowKeyBindingsCmd) disableCmd.AddCommand(disableArrowKeyBindingsGlobalCmd) @@ -32,6 +57,11 @@ func Execute() status.Code { debugCmd.AddCommand(debugReloadCmd) debugCmd.AddCommand(debugInspectCmd) debugCmd.AddCommand(debugOutputCmd) + + rootCmd.AddCommand(statusCmd) + + rootCmd.AddCommand(updateCmd) + if err := rootCmd.Execute(); err != nil { fmt.Println(err) return status.Fail diff --git a/cmd/control/cmd/status.go b/cmd/control/cmd/status.go new file mode 100644 index 0000000..a4ea064 --- /dev/null +++ b/cmd/control/cmd/status.go @@ -0,0 +1,80 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "strconv" + + "github.com/curusarn/resh/cmd/control/status" + "github.com/curusarn/resh/pkg/msg" + "github.com/spf13/cobra" +) + +var statusCmd = &cobra.Command{ + Use: "status", + Short: "show RESH status (aka systemctl status)", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("resh " + version) + fmt.Println() + fmt.Println("Resh versions ...") + fmt.Println(" * installed: " + version + " (" + commit + ")") + resp, err := getDaemonStatus(config.Port) + if err != nil { + fmt.Println(" * daemon: NOT RUNNING!") + } else { + fmt.Println(" * daemon: " + resp.Version + " (" + resp.Commit + ")") + } + versionEnv, found := os.LookupEnv("__RESH_VERSION") + if found == false { + versionEnv = "UNKNOWN!" + } + commitEnv, found := os.LookupEnv("__RESH_REVISION") + if found == false { + commitEnv = "unknown" + } + fmt.Println(" * this session: " + versionEnv + " (" + commitEnv + ")") + if version != resp.Version || version != versionEnv { + fmt.Println(" * THERE IS A MISMATCH BETWEEN VERSIONS!") + fmt.Println(" * Please REPORT this here: https://github.com/curusarn/resh/issues") + fmt.Println(" * Please RESTART this terminal window") + } + + fmt.Println() + fmt.Println("Arrow key bindnigs ...") + if config.BindArrowKeysBash { + fmt.Println(" * bash future sessions: ENABLED (not recommended)") + } else { + fmt.Println(" * bash future sessions: DISABLED (recommended)") + } + if config.BindArrowKeysZsh { + fmt.Println(" * zsh future sessions: ENABLED (recommended)") + } else { + fmt.Println(" * zsh future sessions: DISABLED (not recommended)") + } + exitCode = status.ReshStatus + }, +} + +func getDaemonStatus(port int) (msg.StatusResponse, error) { + mess := msg.StatusResponse{} + url := "http://localhost:" + strconv.Itoa(port) + "/status" + resp, err := http.Get(url) + if err != nil { + log.Println("Daemon is not running!", err) + return mess, err + } + defer resp.Body.Close() + jsn, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Fatal("Error while reading 'daemon /status' response:", err) + } + err = json.Unmarshal(jsn, &mess) + if err != nil { + log.Fatal("Error while decoding 'daemon /status' response:", err) + } + return mess, nil +} diff --git a/cmd/control/cmd/update.go b/cmd/control/cmd/update.go new file mode 100644 index 0000000..7133fd4 --- /dev/null +++ b/cmd/control/cmd/update.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "os" + "os/exec" + + "github.com/curusarn/resh/cmd/control/status" + "github.com/spf13/cobra" +) + +var updateCmd = &cobra.Command{ + Use: "update", + Short: "checks for updates and updates RESH", + Run: func(cmd *cobra.Command, args []string) { + url := "https://raw.githubusercontent.com/curusarn/resh/master/scripts/rawinstall.sh" + execCmd := exec.Command("bash", "-c", "curl -fsSL "+url+" | bash") + execCmd.Stdout = os.Stdout + execCmd.Stderr = os.Stderr + err := execCmd.Run() + if err == nil { + exitCode = status.Success + } + }, +} diff --git a/cmd/control/main.go b/cmd/control/main.go index 633f5e5..ecae4e0 100644 --- a/cmd/control/main.go +++ b/cmd/control/main.go @@ -13,5 +13,5 @@ var version string var commit string func main() { - os.Exit(int(cmd.Execute())) + os.Exit(int(cmd.Execute(version, commit))) } diff --git a/cmd/control/status/status.go b/cmd/control/status/status.go index 2d3bf37..d39adb4 100644 --- a/cmd/control/status/status.go +++ b/cmd/control/status/status.go @@ -8,12 +8,20 @@ const ( Success Code = 0 // Fail exit code Fail = 1 + // EnableResh exit code - tells reshctl() wrapper to enable resh + // EnableResh = 100 + // EnableArrowKeyBindings exit code - tells reshctl() wrapper to enable arrow key bindings EnableArrowKeyBindings = 101 + // DisableResh exit code - tells reshctl() wrapper to enable resh + // DisableResh = 110 + // DisableArrowKeyBindings exit code - tells reshctl() wrapper to disable arrow key bindings DisableArrowKeyBindings = 111 // ReloadRcFiles exit code - tells reshctl() wrapper to reload shellrc resh file ReloadRcFiles = 200 // InspectSessionHistory exit code - tells reshctl() wrapper to take current sessionID and send /inspect request to daemon InspectSessionHistory = 201 + // ReshStatus exit code - tells reshctl() wrapper to show RESH status (aka systemctl status) + ReshStatus = 202 ) diff --git a/cmd/daemon/main.go b/cmd/daemon/main.go index 67ff515..9b59d04 100644 --- a/cmd/daemon/main.go +++ b/cmd/daemon/main.go @@ -3,6 +3,7 @@ package main import ( //"flag" + "encoding/json" "io/ioutil" "log" "net/http" @@ -15,6 +16,7 @@ import ( "github.com/BurntSushi/toml" "github.com/curusarn/resh/pkg/cfg" + "github.com/curusarn/resh/pkg/msg" ) // version from git set during build @@ -89,9 +91,20 @@ func main() { } func statusHandler(w http.ResponseWriter, r *http.Request) { - w.Write([]byte("OK; version: " + version + - "; commit: " + commit + "\n")) - log.Println("Status OK") + log.Println("/status START") + resp := msg.StatusResponse{ + Status: true, + Version: version, + Commit: commit, + } + jsn, err := json.Marshal(&resp) + if err != nil { + log.Println("Encoding error:", err) + log.Println("Response:", resp) + return + } + w.Write(jsn) + log.Println("/status END") } func killDaemon(pidfile string) error { diff --git a/pkg/msg/msg.go b/pkg/msg/msg.go index e402904..c44fd59 100644 --- a/pkg/msg/msg.go +++ b/pkg/msg/msg.go @@ -10,3 +10,10 @@ type InspectMsg struct { type MultiResponse struct { CmdLines []string `json:"cmdlines"` } + +// StatusResponse struct +type StatusResponse struct { + Status bool `json:"status"` + Version string `json:"version"` + Commit string `json:"commit"` +} diff --git a/scripts/rawinstall.sh b/scripts/rawinstall.sh index d36d92a..556d258 100755 --- a/scripts/rawinstall.sh +++ b/scripts/rawinstall.sh @@ -24,6 +24,12 @@ version="${tag:1}" # TODO: check if version is numeric echo " * Latest version: $version (git tag: $tag)" + +if [ "${__RESH_VERSION-}" == "$version" ]; then + echo " * Resh is up to date - nothing to do - exiting." + exit 0 +fi + echo if [ "$(uname)" = "Darwin" ]; then diff --git a/scripts/reshctl.sh b/scripts/reshctl.sh index 0eb9fa2..f7957c1 100644 --- a/scripts/reshctl.sh +++ b/scripts/reshctl.sh @@ -38,7 +38,7 @@ __resh_unbind_arrows() { else eval "$__RESH_bindfunc_revert_arrow_up_bind" [ -z "${__RESH_bindfunc_revert_arrow_up_bind_vim+x}" ] || eval "$__RESH_bindfunc_revert_arrow_up_bind_vim" - echo "RESH arrow up binding successfully disabled ✓" + echo "RESH arrow up binding successfully disabled" __RESH_arrow_keys_bind_enabled=0 fi @@ -47,7 +47,7 @@ __resh_unbind_arrows() { else eval "$__RESH_bindfunc_revert_arrow_down_bind" [ -z "${__RESH_bindfunc_revert_arrow_down_bind_vim+x}" ] || eval "$__RESH_bindfunc_revert_arrow_down_bind_vim" - echo "RESH arrow down binding successfully disabled ✓" + echo "RESH arrow down binding successfully disabled" __RESH_arrow_keys_bind_enabled=0 fi return 0 @@ -119,8 +119,20 @@ reshctl() { resh-inspect --sessionID "$__RESH_SESSION_ID" --count "${3-10}" return 0 ;; + 202) + # show status + if [ "${__RESH_arrow_keys_bind_enabled-0}" != 0 ]; then + echo " * this session: ENABLED" + else + echo " * this session: DISABLED" + fi + return 0 + ;; *) - echo "reshctl() FATAL ERROR: unknown status" >&2 + echo "reshctl() FATAL ERROR: unknown status ($_status)" >&2 + echo "Possibly caused by version mismatch between installed resh and resh in this session." >&2 + echo "Please REPORT this issue here: https://github.com/curusarn/resh/issues" >&2 + echo "Please RESTART your terminal window." >&2 return "$_status" ;; esac diff --git a/scripts/shellrc.sh b/scripts/shellrc.sh index a6b9ebc..7144cb5 100644 --- a/scripts/shellrc.sh +++ b/scripts/shellrc.sh @@ -64,8 +64,10 @@ elif [ $__RESH_MACOS -eq 1 ]; then __RESH_RT_SESS_SINCE_BOOT=$(sysctl -n kern.boottime | awk '{print $4}' | sed 's/,//g') fi -__RESH_VERSION=$(resh-collect -version) -__RESH_REVISION=$(resh-collect -revision) +# shellcheck disable=2155 +export __RESH_VERSION=$(resh-collect -version) +# shellcheck disable=2155 +export __RESH_REVISION=$(resh-collect -revision) __resh_run_daemon