diff --git a/cmd/browse.go b/cmd/browse.go index f394f4c..aef4aa2 100644 --- a/cmd/browse.go +++ b/cmd/browse.go @@ -11,14 +11,15 @@ import ( // Browse is executed when you run `stew browse` func Browse(cliInput string) { - sp := constants.LoadingSpinner - stewPath, err := stew.GetStewPath() - stew.CatchAndExit(err) - systemInfo := stew.NewSystemInfo(stewPath) + userOS, userArch, _, systemInfo, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + sp := constants.LoadingSpinner - userOS := systemInfo.Os - userArch := systemInfo.Arch stewBinPath := systemInfo.StewBinPath stewPkgPath := systemInfo.StewPkgPath stewLockFilePath := systemInfo.StewLockFilePath diff --git a/cmd/config.go b/cmd/config.go new file mode 100644 index 0000000..6b86da3 --- /dev/null +++ b/cmd/config.go @@ -0,0 +1,37 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/marwanhawari/stew/constants" + stew "github.com/marwanhawari/stew/lib" +) + +func Config() { + + userOS, _, stewConfig, _, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + stewConfigFilePath, err := stew.GetStewConfigFilePath(userOS) + stew.CatchAndExit(err) + + inputStewPath, err := stew.PromptInput("Set the stewPath. This will contain all stew data other than the binaries.", stewConfig.StewPath) + stew.CatchAndExit(err) + inputStewBinPath, err := stew.PromptInput("Set the stewBinPath. This is where the binaries will be installed by stew.", stewConfig.StewBinPath) + stew.CatchAndExit(err) + + fullStewPath, err := stew.ResolveTilde(inputStewPath) + stew.CatchAndExit(err) + fullStewBinPath, err := stew.ResolveTilde(inputStewBinPath) + stew.CatchAndExit(err) + + newStewConfig := stew.StewConfig{StewPath: fullStewPath, StewBinPath: fullStewBinPath} + err = stew.WriteStewConfigJSON(newStewConfig, stewConfigFilePath) + stew.CatchAndExit(err) + + fmt.Printf("📄 Updated %v\n", constants.GreenColor(stewConfigFilePath)) +} diff --git a/cmd/install.go b/cmd/install.go index 7edd4fa..137d4ac 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -13,6 +13,13 @@ import ( // Install is executed when you run `stew install` func Install(cliInputs []string) { var err error + + userOS, userArch, _, systemInfo, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + for _, cliInput := range cliInputs { if strings.Contains(cliInput, "Stewfile") { cliInputs, err = stew.ReadStewfileContents(cliInput) @@ -28,12 +35,6 @@ func Install(cliInputs []string) { for _, cliInput := range cliInputs { sp := constants.LoadingSpinner - stewPath, err := stew.GetStewPath() - stew.CatchAndExit(err) - systemInfo := stew.NewSystemInfo(stewPath) - - userOS := systemInfo.Os - userArch := systemInfo.Arch stewBinPath := systemInfo.StewBinPath stewPkgPath := systemInfo.StewPkgPath stewLockFilePath := systemInfo.StewLockFilePath diff --git a/cmd/list.go b/cmd/list.go index f9291dc..7490bce 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "os" stew "github.com/marwanhawari/stew/lib" ) @@ -9,12 +10,12 @@ import ( // List is executed when you run `stew list` func List(cliTagsFlag bool, cliAssetsFlag bool) { - stewPath, err := stew.GetStewPath() - stew.CatchAndExit(err) - systemInfo := stew.NewSystemInfo(stewPath) + userOS, userArch, _, systemInfo, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } - userOS := systemInfo.Os - userArch := systemInfo.Arch stewLockFilePath := systemInfo.StewLockFilePath lockFile, err := stew.NewLockFile(stewLockFilePath, userOS, userArch) diff --git a/cmd/rename.go b/cmd/rename.go index 9505ea6..7f91e9a 100644 --- a/cmd/rename.go +++ b/cmd/rename.go @@ -12,15 +12,15 @@ import ( // Rename is executed when you run `stew rename` func Rename(cliInput string) { - err := stew.ValidateCLIInput(cliInput) - stew.CatchAndExit(err) + userOS, userArch, _, systemInfo, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } - stewPath, err := stew.GetStewPath() + err = stew.ValidateCLIInput(cliInput) stew.CatchAndExit(err) - systemInfo := stew.NewSystemInfo(stewPath) - userOS := systemInfo.Os - userArch := systemInfo.Arch stewBinPath := systemInfo.StewBinPath stewLockFilePath := systemInfo.StewLockFilePath diff --git a/cmd/uninstall.go b/cmd/uninstall.go index e6d5db4..9dd2f42 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "os" "github.com/marwanhawari/stew/constants" stew "github.com/marwanhawari/stew/lib" @@ -9,6 +10,13 @@ import ( // Uninstall is executed when you run `stew uninstall` func Uninstall(cliFlag bool, binaryName string) { + + userOS, userArch, _, systemInfo, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + if cliFlag && binaryName != "" { stew.CatchAndExit(stew.CLIFlagAndInputError{}) } else if !cliFlag { @@ -16,12 +24,6 @@ func Uninstall(cliFlag bool, binaryName string) { stew.CatchAndExit(err) } - stewPath, err := stew.GetStewPath() - stew.CatchAndExit(err) - systemInfo := stew.NewSystemInfo(stewPath) - - userOS := systemInfo.Os - userArch := systemInfo.Arch stewBinPath := systemInfo.StewBinPath stewPkgPath := systemInfo.StewPkgPath stewLockFilePath := systemInfo.StewLockFilePath diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 08a85fc..fecaefc 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -11,6 +11,13 @@ import ( // Upgrade is executed when you run `stew upgrade` func Upgrade(cliFlag bool, binaryName string) { + + userOS, userArch, _, systemInfo, err := stew.Initialize() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + if cliFlag && binaryName != "" { stew.CatchAndExit(stew.CLIFlagAndInputError{}) } else if !cliFlag { @@ -20,12 +27,6 @@ func Upgrade(cliFlag bool, binaryName string) { sp := constants.LoadingSpinner - stewPath, err := stew.GetStewPath() - stew.CatchAndExit(err) - systemInfo := stew.NewSystemInfo(stewPath) - - userOS := systemInfo.Os - userArch := systemInfo.Arch stewPkgPath := systemInfo.StewPkgPath stewTmpPath := systemInfo.StewTmpPath stewLockFilePath := systemInfo.StewLockFilePath diff --git a/install.sh b/install.sh index ab27b94..b5dfd9e 100755 --- a/install.sh +++ b/install.sh @@ -1,25 +1,56 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash # This install script does 3 things: -# 1. Create the ~/.stew directory structure +# 1. Create the stew directory structure # 2. Download the stew binary -# 3. Add ~/.stew/bin to PATH in ~/.zshrc or ~/.bashrc +# 3. Add the stew binary path to PATH in ~/.zshrc or ~/.bashrc os="" arch="" exe="" +defaultStewPath="" +configPath="" # Detect os case "$(uname -s)" in Darwin) os="darwin" + + if [ -z "$XDG_DATA_HOME" ] + then + defaultStewPath="$HOME/.local/share/stew" + else + defaultStewPath="$XDG_DATA_HOME/stew" + fi + + if [ -z "$XDG_CONFIG_HOME" ] + then + configPath="$HOME/.config/stew" + else + configPath="$XDG_CONFIG_HOME/stew" + fi ;; Linux) os="linux" + if [ -z "$XDG_DATA_HOME" ] + then + defaultStewPath="$HOME/.local/share/stew" + else + defaultStewPath="$XDG_DATA_HOME/stew" + fi + + if [ -z "$XDG_CONFIG_HOME" ] + then + configPath="$HOME/.config/stew" + else + configPath="$XDG_CONFIG_HOME/stew" + fi ;; CYGWIN*|MSYS*|MINGW*) os="windows" exe=".exe" + defaultStewPath="$HOME/AppData/Local/stew" + configPath="$HOME/AppData/Local/stew/Config" ;; esac @@ -38,27 +69,77 @@ esac if [ "$os" = "" ] || [ "$arch" = "" ] then - echo "\033[31m\033[1mError:\033[0m Your current OS/arch is not supported by stew" + echo "" + echo "|||||||||||||||||||||" + echo "|| Error ||" + echo "|||||||||||||||||||||" + echo "" + echo "Your current OS/arch is not supported by stew" + echo "" exit 1 fi -# 1. Create the ~/.stew directory structure -mkdir -p "$HOME"/.stew/bin -mkdir -p "$HOME"/.stew/pkg +# 1. Create the stew directory structure +stewPath="" +stewBinPath="" + +read -r -t 60 -p "Set the stewPath. This will contain all stew data other than the binaries. (${defaultStewPath}): " stewPathInput +if [ -z "$stewPathInput" ] +then + stewPath="${defaultStewPath}" +else + stewPath="${stewPathInput/#~/$HOME}" + stewPath="${stewPath/#\$HOME/$HOME}" + stewPath="${stewPath/#\$PWD/$PWD}" + if [ -x "$(command -v dirname)" ] && [ -x "$(command -v basename)" ] + then + stewPath="$(cd "$(dirname "$stewPath")" || exit; pwd)/$(basename "$stewPath")" + fi +fi + +read -r -t 60 -p "Set the stewBinPath. This is where the binaries will be installed by stew. (${defaultStewPath}/bin): " stewBinPathInput +if [ -z "$stewBinPathInput" ] +then + stewBinPath="${defaultStewPath}/bin" +else + stewBinPath="${stewBinPathInput/#~/$HOME}" + stewBinPath="${stewBinPath/#\$HOME/$HOME}" + stewBinPath="${stewBinPath/#\$PWD/$PWD}" + if [ -x "$(command -v dirname)" ] && [ -x "$(command -v basename)" ] + then + stewBinPath="$(cd "$(dirname "$stewBinPath")" || exit; pwd)/$(basename "$stewBinPath")" + fi +fi + +mkdir -p "${stewPath}/bin" +mkdir -p "${stewPath}/pkg" +mkdir -p "${stewBinPath}" +mkdir -p "${configPath}" + +echo "{ + \"stewPath\": \"${stewPath}\", + \"stewBinPath\": \"${stewBinPath}\" +}" > "${configPath}/config.json" # 2. Download the stew binary -curl -o "$HOME"/.stew/bin/stew${exe} -fsSL https://github.com/marwanhawari/stew/releases/latest/download/stew-${os}-${arch}${exe} -chmod +x "$HOME"/.stew/bin/stew${exe} +curl -o "${stewBinPath}/stew${exe}" -fsSL https://github.com/marwanhawari/stew/releases/latest/download/stew-${os}-${arch}${exe} +chmod +x "${stewBinPath}/stew${exe}" -# 3. Add ~/.stew/bin to PATH in ~/.zshrc or ~/.bashrc +# 3. Add the stew binary path to PATH in ~/.zshrc or ~/.bashrc if [ -f "$HOME"/.zshrc ] then - echo 'export PATH="$HOME/.stew/bin:$PATH"' >> "$HOME"/.zshrc + echo "export PATH=\"${stewBinPath}:\$PATH\"" >> "$HOME"/.zshrc elif [ -f "$HOME"/.bashrc ] then - echo 'export PATH="$HOME/.stew/bin:$PATH"' >> "$HOME"/.bashrc + echo "export PATH=\"${stewBinPath}:\$PATH\"" >> "$HOME"/.bashrc else - echo "Make sure to add $HOME/.stew/bin to PATH" + echo "Make sure to add ${stewBinPath} to PATH" fi -echo "\033[32m\033[1mSuccess:\033[0m Start a new terminal session to start using stew" +echo "" +echo "|||||||||||||||||||||" +echo "|| Success ||" +echo "|||||||||||||||||||||" +echo "" +echo "Start a new terminal session to start using stew" +echo "" diff --git a/lib/config.go b/lib/config.go new file mode 100644 index 0000000..ea20078 --- /dev/null +++ b/lib/config.go @@ -0,0 +1,231 @@ +package stew + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "runtime" +) + +// GetDefaultStewPath will return the default path to the top-level stew directory +func GetDefaultStewPath(userOS string) (string, error) { + + homeDir, err := os.UserHomeDir() + if err != nil { + return "", err + } + + var stewPath string + switch userOS { + case "windows": + stewPath = filepath.Join(homeDir, "AppData", "Local", "stew") + default: + xdgDataHomePath := os.Getenv("XDG_DATA_HOME") + if xdgDataHomePath == "" { + stewPath = filepath.Join(homeDir, ".local", "share", "stew") + } else { + stewPath = filepath.Join(xdgDataHomePath, "stew") + + } + } + + return stewPath, nil +} + +// GetDefaultStewBinPath will return the default path where binaries are installed by stew +func GetDefaultStewBinPath(userOS string) (string, error) { + + homeDir, err := os.UserHomeDir() + if err != nil { + return "", err + } + + var stewBinPath string + switch userOS { + case "windows": + stewBinPath = filepath.Join(homeDir, "AppData", "Local", "stew", "bin") + default: + xdgDataHomePath := os.Getenv("XDG_DATA_HOME") + if xdgDataHomePath == "" { + stewBinPath = filepath.Join(homeDir, ".local", "share", "stew", "bin") + } else { + stewBinPath = filepath.Join(xdgDataHomePath, "stew", "bin") + + } + } + + return stewBinPath, nil +} + +// GetStewConfigFilePath will return the stew config file path +func GetStewConfigFilePath(userOS string) (string, error) { + + homeDir, err := os.UserHomeDir() + if err != nil { + return "", err + } + + var stewConfigFilePath string + switch userOS { + case "windows": + stewConfigFilePath = filepath.Join(homeDir, "AppData", "Local", "stew", "Config", "config.json") + default: + xdgConfigHomePath := os.Getenv("XDG_CONFIG_HOME") + if xdgConfigHomePath == "" { + stewConfigFilePath = filepath.Join(homeDir, ".config", "stew", "config.json") + } else { + stewConfigFilePath = filepath.Join(xdgConfigHomePath, "stew", "config.json") + } + } + + return stewConfigFilePath, nil +} + +// StewConfig contains all the stew configuration data +type StewConfig struct { + StewPath string `json:"stewPath"` + StewBinPath string `json:"stewBinPath"` +} + +func readStewConfigJSON(stewConfigFilePath string) (StewConfig, error) { + + stewConfigFileBytes, err := ioutil.ReadFile(stewConfigFilePath) + if err != nil { + return StewConfig{}, err + } + + var stewConfig StewConfig + err = json.Unmarshal(stewConfigFileBytes, &stewConfig) + if err != nil { + return StewConfig{}, err + } + + return stewConfig, nil +} + +// WriteStewConfigJSON will write the config JSON file +func WriteStewConfigJSON(stewConfigFileJSON StewConfig, outputPath string) error { + + stewConfigFileBytes, err := json.MarshalIndent(stewConfigFileJSON, "", "\t") + if err != nil { + return err + } + + err = ioutil.WriteFile(outputPath, stewConfigFileBytes, 0644) + if err != nil { + return err + } + + return nil +} + +// NewStewConfig creates a new instance of the StewConfig struct +func NewStewConfig(userOS string) (StewConfig, error) { + var stewConfig StewConfig + + stewConfigFilePath, err := GetStewConfigFilePath(userOS) + if err != nil { + return StewConfig{}, err + } + defaultStewPath, err := GetDefaultStewPath(userOS) + if err != nil { + return StewConfig{}, err + } + defaultStewBinPath, err := GetDefaultStewBinPath(userOS) + if err != nil { + return StewConfig{}, err + } + + configExists, err := PathExists(stewConfigFilePath) + if err != nil { + return StewConfig{}, err + } + if configExists { + stewConfig, err = readStewConfigJSON(stewConfigFilePath) + if err != nil { + return StewConfig{}, err + } + } + + if stewConfig.StewPath == "" { + stewConfig.StewPath = defaultStewPath + } + + if stewConfig.StewBinPath == "" { + stewConfig.StewBinPath = defaultStewBinPath + } + + err = createStewDirsAndFiles(stewConfig, stewConfigFilePath) + if err != nil { + return StewConfig{}, err + } + + return stewConfig, nil +} + +func createStewDirsAndFiles(stewConfig StewConfig, stewConfigFilePath string) error { + var err error + + err = os.MkdirAll(stewConfig.StewPath, 0755) + if err != nil { + return err + } + err = os.MkdirAll(filepath.Join(stewConfig.StewPath, "bin"), 0755) + if err != nil { + return err + } + err = os.MkdirAll(filepath.Join(stewConfig.StewPath, "pkg"), 0755) + if err != nil { + return err + } + + err = os.MkdirAll(stewConfig.StewBinPath, 0755) + if err != nil { + return err + } + + err = os.MkdirAll(filepath.Dir(stewConfigFilePath), 0755) + if err != nil { + return err + } + err = WriteStewConfigJSON(stewConfig, stewConfigFilePath) + if err != nil { + return err + } + + return nil +} + +// SystemInfo contains system specific info like OS, arch, and ~/.stew paths +type SystemInfo struct { + StewPath string + StewBinPath string + StewPkgPath string + StewLockFilePath string + StewTmpPath string +} + +// NewSystemInfo creates a new instance of the SystemInfo struct +func NewSystemInfo(stewConfig StewConfig) SystemInfo { + var systemInfo SystemInfo + systemInfo.StewPath = stewConfig.StewPath + systemInfo.StewBinPath = stewConfig.StewBinPath + systemInfo.StewPkgPath = filepath.Join(stewConfig.StewPath, "pkg") + systemInfo.StewLockFilePath = filepath.Join(stewConfig.StewPath, "Stewfile.lock.json") + systemInfo.StewTmpPath = filepath.Join(stewConfig.StewPath, "tmp") + return systemInfo +} + +// Initialize returns pertinent initialization information like OS, arch, configuration, and system info +func Initialize() (string, string, StewConfig, SystemInfo, error) { + userOS := runtime.GOOS + userArch := runtime.GOARCH + stewConfig, err := NewStewConfig(userOS) + if err != nil { + return "", "", StewConfig{}, SystemInfo{}, err + } + systemInfo := NewSystemInfo(stewConfig) + + return userOS, userArch, stewConfig, systemInfo, nil +} diff --git a/lib/config_test.go b/lib/config_test.go new file mode 100644 index 0000000..a93a2cc --- /dev/null +++ b/lib/config_test.go @@ -0,0 +1,52 @@ +package stew + +import ( + "os" + "path/filepath" + "testing" +) + +func TestGetDefaultStewPath(t *testing.T) { + homeDir, err := os.UserHomeDir() + if err != nil { + t.Errorf("Could not get os.UserHomeDir()") + } + type args struct { + userOS string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "test1", + args: args{ + userOS: "darwin", + }, + want: filepath.Join(homeDir, ".local", "share", "stew"), + wantErr: false, + }, + { + name: "test2", + args: args{ + userOS: "windows", + }, + want: filepath.Join(homeDir, "AppData", "Local", "stew"), + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetDefaultStewPath(tt.args.userOS) + if (err != nil) != tt.wantErr { + t.Errorf("GetDefaultStewPath() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("GetDefaultStewPath() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/lib/stewfile.go b/lib/stewfile.go index f8def87..cde7aef 100644 --- a/lib/stewfile.go +++ b/lib/stewfile.go @@ -116,31 +116,6 @@ func NewLockFile(stewLockFilePath, userOS, userArch string) (LockFile, error) { return lockFile, nil } -// SystemInfo contains system specific info like OS, arch, and ~/.stew paths -type SystemInfo struct { - Os string - Arch string - StewPath string - StewBinPath string - StewPkgPath string - StewLockFilePath string - StewTmpPath string -} - -// NewSystemInfo creates a new instance of the SystemInfo struct -func NewSystemInfo(stewPath string) SystemInfo { - var systemInfo SystemInfo - systemInfo.StewPath = stewPath - systemInfo.StewBinPath = filepath.Join(stewPath, "bin") - systemInfo.StewPkgPath = filepath.Join(stewPath, "pkg") - systemInfo.StewLockFilePath = filepath.Join(stewPath, "Stewfile.lock.json") - systemInfo.StewTmpPath = filepath.Join(stewPath, "tmp") - systemInfo.Os = getOS() - systemInfo.Arch = getArch() - - return systemInfo -} - // DeleteAssetAndBinary will delete the asset from the ~/.stew/pkg path and delete the binary from the ~/.stew/bin path func DeleteAssetAndBinary(stewPkgPath, stewBinPath, asset, binary string) error { assetPath := filepath.Join(stewPkgPath, asset) diff --git a/lib/stewfile_test.go b/lib/stewfile_test.go index 3934af0..be1e48a 100644 --- a/lib/stewfile_test.go +++ b/lib/stewfile_test.go @@ -5,7 +5,6 @@ import ( "os" "path/filepath" "reflect" - "runtime" "testing" ) @@ -305,9 +304,13 @@ func TestNewSystemInfo(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tempDir := t.TempDir() + + testStewConfig := StewConfig{ + StewPath: tempDir, + StewBinPath: filepath.Join(tempDir, "bin"), + } + testSystemInfo := SystemInfo{ - Os: runtime.GOOS, - Arch: runtime.GOARCH, StewPath: tempDir, StewBinPath: filepath.Join(tempDir, "bin"), StewPkgPath: filepath.Join(tempDir, "pkg"), @@ -315,7 +318,7 @@ func TestNewSystemInfo(t *testing.T) { StewTmpPath: filepath.Join(tempDir, "tmp"), } - got := NewSystemInfo(tempDir) + got := NewSystemInfo(testStewConfig) if !reflect.DeepEqual(got, testSystemInfo) { t.Errorf("NewSystemInfo() = %v, want %v", got, testSystemInfo) } diff --git a/lib/ui.go b/lib/ui.go index 168d35c..8ad8737 100644 --- a/lib/ui.go +++ b/lib/ui.go @@ -21,6 +21,23 @@ func PromptSelect(message string, options []string) (string, error) { return result, nil } +// PromptInput launches the input UI +func PromptInput(message string, defaultInput string) (string, error) { + result := "" + prompt := &survey.Input{ + Message: message, + Default: defaultInput, + } + err := survey.AskOne(prompt, &result, survey.WithIcons(func(icons *survey.IconSet) { + icons.Question.Text = "*" + })) + if err != nil { + return "", ExitUserSelectionError{Err: err} + } + + return result, nil +} + // WarningPromptSelect launches the selection UI with a warning styling func WarningPromptSelect(message string, options []string) (string, error) { result := "" diff --git a/lib/util.go b/lib/util.go index a04e785..ad08a4d 100644 --- a/lib/util.go +++ b/lib/util.go @@ -7,7 +7,6 @@ import ( "os" "path/filepath" "regexp" - "runtime" "strings" "github.com/marwanhawari/stew/constants" @@ -39,12 +38,6 @@ func isExecutableFile(filePath string) (bool, error) { func CatchAndExit(err error) { if err != nil { fmt.Println(err) - stewPath, _ := GetStewPath() - stewTmpPath := filepath.Join(stewPath, "tmp") - err = os.RemoveAll(stewTmpPath) - if err != nil { - fmt.Println(err) - } os.Exit(1) } } @@ -63,25 +56,6 @@ func PathExists(path string) (bool, error) { return true, nil } -// GetStewPath will return the path to the top-level stew directory -func GetStewPath() (string, error) { - homeDir, err := os.UserHomeDir() - if err != nil { - return "", err - } - - stewPath := filepath.Join(homeDir, ".stew") - - exists, err := PathExists(stewPath) - if err != nil { - return "", err - } else if !exists { - return "", StewpathNotFoundError{StewPath: stewPath} - } - - return stewPath, nil -} - // DownloadFile will download a file from url to a given path func DownloadFile(downloadPath string, url string) error { sp := constants.LoadingSpinner @@ -292,14 +266,6 @@ func Contains(slice []string, target string) (int, bool) { return -1, false } -func getOS() string { - return runtime.GOOS -} - -func getArch() string { - return runtime.GOARCH -} - func extractBinary(downloadedFilePath, tmpExtractionPath string) error { isArchive := isArchiveFile(downloadedFilePath) if isArchive { @@ -411,3 +377,17 @@ func PromptRenameBinary(originalBinaryName string) (string, error) { } return renamedBinaryName, nil } + +// ResolveTilde will resolve the full path for an input path beginning with ~ +func ResolveTilde(filePath string) (string, error) { + if strings.HasPrefix(filePath, "~") { + homeDir, err := os.UserHomeDir() + if err != nil { + return "", err + } + + return filepath.Join(homeDir, filePath[2:]), nil + } + + return filePath, nil +} diff --git a/lib/util_test.go b/lib/util_test.go index 9157589..1434abb 100644 --- a/lib/util_test.go +++ b/lib/util_test.go @@ -5,7 +5,6 @@ import ( "os" "path/filepath" "reflect" - "runtime" "testing" ) @@ -138,41 +137,6 @@ func TestPathExists(t *testing.T) { } } -func TestGetStewPath(t *testing.T) { - tests := []struct { - name string - wantErr bool - }{ - { - name: "test1", - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - homeDir, _ := os.UserHomeDir() - testStewPath := filepath.Join(homeDir, ".stew") - stewPathExists, _ := PathExists(testStewPath) - if !stewPathExists { - os.MkdirAll(testStewPath, 0755) - } - - got, err := GetStewPath() - if !stewPathExists { - os.RemoveAll(testStewPath) - } - - if (err != nil) != tt.wantErr { - t.Errorf("GetStewPath() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != testStewPath { - t.Errorf("GetStewPath() = %v, want %v", got, testStewPath) - } - }) - } -} - func TestDownloadFile(t *testing.T) { type args struct { url string @@ -650,44 +614,6 @@ func TestContains(t *testing.T) { } } -func Test_getOS(t *testing.T) { - tests := []struct { - name string - want string - }{ - { - name: "test1", - want: runtime.GOOS, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := getOS(); got != tt.want { - t.Errorf("getOS() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_getArch(t *testing.T) { - tests := []struct { - name string - want string - }{ - { - name: "test1", - want: runtime.GOARCH, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := getArch(); got != tt.want { - t.Errorf("getArch() = %v, want %v", got, tt.want) - } - }) - } -} - func Test_extractBinary(t *testing.T) { type args struct { downloadedFilePath string @@ -735,10 +661,15 @@ func TestInstallBinary(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tempDir := t.TempDir() - stewPath := filepath.Join(tempDir, ".stew") repo := "ppath" - systemInfo := NewSystemInfo(stewPath) + + testStewConfig := StewConfig{ + StewPath: tempDir, + StewBinPath: filepath.Join(tempDir, "bin"), + } + + systemInfo := NewSystemInfo(testStewConfig) os.MkdirAll(systemInfo.StewBinPath, 0755) os.MkdirAll(systemInfo.StewPkgPath, 0755) os.MkdirAll(systemInfo.StewTmpPath, 0755) @@ -794,10 +725,15 @@ func TestInstallBinary_Fail(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tempDir := t.TempDir() - stewPath := filepath.Join(tempDir, ".stew") repo := "ppath" - systemInfo := NewSystemInfo(stewPath) + + testStewConfig := StewConfig{ + StewPath: tempDir, + StewBinPath: filepath.Join(tempDir, "bin"), + } + + systemInfo := NewSystemInfo(testStewConfig) os.MkdirAll(systemInfo.StewBinPath, 0755) os.MkdirAll(systemInfo.StewPkgPath, 0755) os.MkdirAll(systemInfo.StewTmpPath, 0755) diff --git a/main.go b/main.go index d83365f..3a1b45e 100644 --- a/main.go +++ b/main.go @@ -73,7 +73,7 @@ func main() { }, { Name: "rename", - Usage: "Rename an installed binary using a prompt UI. [Ex: stew rename fzf]", + Usage: "Rename an installed binary using an interactive UI. [Ex: stew rename fzf]", Aliases: []string{"re"}, Action: func(c *cli.Context) error { cmd.Rename(c.Args().First()) @@ -99,6 +99,14 @@ func main() { return nil }, }, + { + Name: "config", + Usage: "Configure the stew file paths using an interactive UI. [Ex: stew config]", + Action: func(c *cli.Context) error { + cmd.Config() + return nil + }, + }, }, }