Repository: JanDeDobbeleer/oh-my-posh
Pull request #2877 (2022-10-04 17:47:20)

noonish
### Prerequisites

- [x] I have read and understood the [contributing guide][CONTRIBUTING.md]
- [x] The commit message follows the [conventional commits][cc] guidelines
- [x] Tests for the changes have been added (for bug fixes/features)
- [x] Docs have been added/updated (for bug fixes/features)

### Description

- fix(language): do not error when not installed
- fix(pwsh): move HOME on invalid directory

<!---

Tips:

If you're not comfortable with working with Git, we're working a guide (https://ohmyposh.dev/docs/contributing_git) to help you out.
Oh My Posh advises GitKraken (https://www.gitkraken.com/invite/nQmDPR9D) as your preferred cross platform Git GUI power tool.

-->

[CONTRIBUTING.md]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/CONTRIBUTING.md
[cc]: https://www.conventionalcommits.org/en/v1.0.0/#summary



Patch:
diff --git a/src/segments/angular.go b/src/segments/angular.go
index dcefa16f..ab22d940 100644
--- a/src/segments/angular.go
+++ b/src/segments/angular.go
@@ -33,7 +33,7 @@ func (a *Angular) Enabled() bool {
 	return a.language.Enabled()
 }
 
-func (a *Angular) getVersion() (string, error) {
+func (a *Angular) getVersion() string {
 	// tested by nx_test.go
 	return getNodePackageVersion(a.language.env, filepath.Join("@angular", "core"))
 }
diff --git a/src/segments/golang.go b/src/segments/golang.go
index 0dcd1c19..bd076443 100644
--- a/src/segments/golang.go
+++ b/src/segments/golang.go
@@ -39,20 +39,22 @@ func (g *Golang) Init(props properties.Properties, env environment.Environment)
 	}
 }
 
-func (g *Golang) getVersion() (string, error) {
+func (g *Golang) getVersion() string {
 	if !g.props.GetBool(ParseModFile, false) {
-		return "", nil
+		return ""
 	}
 	gomod, err := g.language.env.HasParentFilePath("go.mod")
 	if err != nil {
-		return "", nil
+		g.env.Log(environment.Debug, "getVersion", err.Error())
+		return ""
 	}
 	contents := g.language.env.FileContent(gomod.Path)
 	file, err := modfile.Parse(gomod.Path, []byte(contents), nil)
 	if err != nil {
-		return "", err
+		g.env.Log(environment.Debug, "getVersion", err.Error())
+		return ""
 	}
-	return file.Go.Version, nil
+	return file.Go.Version
 }
 
 func (g *Golang) Enabled() bool {
diff --git a/src/segments/language.go b/src/segments/language.go
index f23351d6..e48aac4b 100644
--- a/src/segments/language.go
+++ b/src/segments/language.go
@@ -17,7 +17,7 @@ type loadContext func()
 
 type inContext func() bool
 
-type getVersion func() (string, error)
+type getVersion func() string
 type matchesVersionFile func() bool
 
 type version struct {
@@ -171,9 +171,8 @@ func (l *language) setVersion() error {
 				continue
 			}
 		} else {
-			versionStr, err = command.getVersion()
-			if err != nil || versionStr == "" {
-				lastError = errors.New("cannot get version")
+			versionStr = command.getVersion()
+			if len(versionStr) == 0 {
 				continue
 			}
 		}
diff --git a/src/segments/nx.go b/src/segments/nx.go
index f37bbf94..a8b3e85f 100644
--- a/src/segments/nx.go
+++ b/src/segments/nx.go
@@ -35,21 +35,23 @@ func (a *Nx) Enabled() bool {
 	return a.language.Enabled()
 }
 
-func (a *Nx) getVersion() (string, error) {
+func (a *Nx) getVersion() string {
 	return getNodePackageVersion(a.language.env, "nx")
 }
 
-func getNodePackageVersion(env environment.Environment, nodePackage string) (string, error) {
+func getNodePackageVersion(env environment.Environment, nodePackage string) string {
 	const fileName string = "package.json"
 	folder := filepath.Join(env.Pwd(), "node_modules", nodePackage)
 	if !env.HasFilesInDir(folder, fileName) {
-		return "", fmt.Errorf("%s not found in %s", fileName, folder)
+		env.Log(environment.Debug, "getNodePackageVersion", fmt.Sprintf("%s not found in %s", fileName, folder))
+		return ""
 	}
 	content := env.FileContent(filepath.Join(folder, fileName))
 	var data ProjectData
 	err := json.Unmarshal([]byte(content), &data)
 	if err != nil {
-		return "", err
+		env.Log(environment.Debug, "getNodePackageVersion", err.Error())
+		return ""
 	}
-	return data.Version, nil
+	return data.Version
 }
diff --git a/src/segments/python.go b/src/segments/python.go
index 5ff49e5c..aca3202d 100644
--- a/src/segments/python.go
+++ b/src/segments/python.go
@@ -1,7 +1,6 @@
 package segments
 
 import (
-	"errors"
 	"fmt"
 	"oh-my-posh/environment"
 	"oh-my-posh/properties"
@@ -99,7 +98,7 @@ func (p *Python) canUseVenvName(name string) bool {
 	return true
 }
 
-func (p *Python) pyenvVersion() (string, error) {
+func (p *Python) pyenvVersion() string {
 	// Use `pyenv root` instead of $PYENV_ROOT?
 	// Is our Python executable at $PYENV_ROOT/bin/python ?
 	// Should p.env expose command paths?
@@ -108,37 +107,43 @@ func (p *Python) pyenvVersion() (string, error) {
 		path = p.env.CommandPath("python3")
 	}
 	if len(path) == 0 {
-		return "", errors.New("no python executable found")
+		p.env.Log(environment.Debug, "pyenvVersion", "python not found")
+		return ""
 	}
 	pyEnvRoot := p.env.Getenv("PYENV_ROOT")
 	// TODO:  pyenv-win has this at $PYENV_ROOT/pyenv-win/shims
 	if path != filepath.Join(pyEnvRoot, "shims", "python") {
-		return "", fmt.Errorf("executable at %s is not a pyenv shim", path)
+		p.env.Log(environment.Debug, "pyenvVersion", fmt.Sprintf("executable at %s is not a pyenv shim", path))
+		return ""
 	}
 	// pyenv version-name will return current version or virtualenv
 	cmdOutput, err := p.env.RunCommand("pyenv", "version-name")
 	if err != nil {
-		return "", err
+		p.env.Log(environment.Debug, "pyenvVersion", err.Error())
+		return ""
 	}
 	versionString := strings.Split(cmdOutput, ":")[0]
 	if len(versionString) == 0 {
-		return "", errors.New("no pyenv version-name found")
+		p.env.Log(environment.Debug, "pyenvVersion", "no pyenv version-name found")
+		return ""
 	}
 
 	// $PYENV_ROOT/versions + versionString (symlinks resolved) == $PYENV_ROOT/versions/(version)[/envs/(virtualenv)]
 	realPath, err := p.env.ResolveSymlink(filepath.Join(pyEnvRoot, "versions", versionString))
 	if err != nil {
-		return "", err
+		p.env.Log(environment.Debug, "pyenvVersion", err.Error())
+		return ""
 	}
 	// ../versions/(version)[/envs/(virtualenv)]
 	shortPath, err := filepath.Rel(filepath.Join(pyEnvRoot, "versions"), realPath)
 	if err != nil {
-		return "", err
+		p.env.Log(environment.Debug, "pyenvVersion", err.Error())
+		return ""
 	}
 	// override virtualenv if pyenv set one
 	parts := strings.Split(shortPath, string(filepath.Separator))
 	if len(parts) > 2 && p.canUseVenvName(parts[2]) {
 		p.Venv = parts[2]
 	}
-	return parts[0], nil
+	return parts[0]
 }
diff --git a/src/shell/scripts/omp.ps1 b/src/shell/scripts/omp.ps1
index 335fb6c2..749e2b2b 100644
--- a/src/shell/scripts/omp.ps1
+++ b/src/shell/scripts/omp.ps1
@@ -83,6 +83,12 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
         $StartInfo.RedirectStandardError = $StartInfo.RedirectStandardInput = $StartInfo.RedirectStandardOutput = $true
         $StartInfo.UseShellExecute = $false
         if ($PWD.Provider.Name -eq 'FileSystem') {
+            # make sure we're in a valid directory
+            # if not, go back HOME
+            if (-not (Test-Path -Path $PWD)) {
+                Write-Host "Unable to find the current directory, falling back to $HOME" -ForegroundColor Red
+                Set-Location $HOME
+            }
             $StartInfo.WorkingDirectory = $PWD.ProviderPath
         }
         $StartInfo.CreateNoWindow = $true


Test patch:
diff --git a/src/segments/golang_test.go b/src/segments/golang_test.go
index ef4941d4..fd094b0a 100644
--- a/src/segments/golang_test.go
+++ b/src/segments/golang_test.go
@@ -10,6 +10,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	mock2 "github.com/stretchr/testify/mock"
 )
 
 type mockedLanguageParams struct {
@@ -29,6 +30,7 @@ func getMockedLanguageEnv(params *mockedLanguageParams) (*mock.MockedEnvironment
 	env.On("TemplateCache").Return(&environment.TemplateCache{
 		Env: make(map[string]string),
 	})
+	env.On("Log", mock2.Anything, mock2.Anything, mock2.Anything)
 	props := properties.Map{
 		properties.FetchVersion: true,
 	}
diff --git a/src/segments/nx_test.go b/src/segments/nx_test.go
index 216e955b..5c7aeb01 100644
--- a/src/segments/nx_test.go
+++ b/src/segments/nx_test.go
@@ -7,6 +7,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	mock2 "github.com/stretchr/testify/mock"
 )
 
 func TestGetNodePackageVersion(t *testing.T) {
@@ -33,12 +34,12 @@ func TestGetNodePackageVersion(t *testing.T) {
 		env.On("TemplateCache").Return(&environment.TemplateCache{
 			Env: make(map[string]string),
 		})
-		got, err := getNodePackageVersion(env, "nx")
+		env.On("Log", mock2.Anything, mock2.Anything, mock2.Anything)
+		got := getNodePackageVersion(env, "nx")
 		if tc.ShouldFail {
-			assert.Error(t, err, tc.Case)
+			assert.Empty(t, got, tc.Case)
 			return
 		}
-		assert.Nil(t, err, tc.Case)
 		assert.Equal(t, tc.Version, got, tc.Case)
 	}
 }
diff --git a/src/segments/python_test.go b/src/segments/python_test.go
index d53b132b..f85f875e 100644
--- a/src/segments/python_test.go
+++ b/src/segments/python_test.go
@@ -93,6 +93,7 @@ func TestPythonTemplate(t *testing.T) {
 		env.On("Pwd").Return("/usr/home/project")
 		env.On("Home").Return("/usr/home")
 		env.On("ResolveSymlink", mock2.Anything).Return(tc.ResolveSymlink.Path, tc.ResolveSymlink.Err)
+		env.On("Log", mock2.Anything, mock2.Anything, mock2.Anything)
 		props := properties.Map{
 			properties.FetchVersion: tc.FetchVersion,
 			UsePythonVersionFile:    true,