Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: resolve nushell support issue #397

Merged
merged 2 commits into from
Jan 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@

coverage.out
**/available.cache

vfox
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
[![GitHub Release](https://img.shields.io/github/v/release/version-fox/vfox?display_name=tag&style=for-the-badge)](https://github.com/version-fox/vfox/releases)
[![Discord](https://img.shields.io/discord/1191981003204477019?style=for-the-badge&logo=discord)](https://discord.gg/85c8ptYgb7)

[[English]](./README.md) [[中文文档]](./README_CN.md)
[[English]](./README.md) [[中文文档]](./README_CN.md)

If you **switch between development projects which expect different environments**, specifically different runtime versions or ambient libraries,
or **you are tired of all kinds of cumbersome environment configurations**, `vfox` is the ideal choice for you.

## Introduction

**`vfox` is a cross-platform version manager(similar to `nvm`, `fvm`, `sdkman`, `asdf-vm`, etc.), extendable via plugins**. It allows you to quickly install
Expand Down Expand Up @@ -57,13 +58,14 @@ if (-not (Test-Path -Path $PROFILE)) { New-Item -Type File -Path $PROFILE -Force
# 3. copy internal/shell/clink_vfox.lua to script path

# For Nushell:
vfox activate nushell | save --append $nu.config-path
vfox activate nushell $nu.default-config-dir | save --append $nu.config-path
```

> Remember to restart your shell to apply the changes.

#### 3. Add an SDK plugin
```bash

```bash
$ vfox add nodejs
```

Expand Down Expand Up @@ -93,8 +95,8 @@ Our future plans and high priority features and enhancements are:
- Introducing plugin templates to facilitate multi-file plugin development.
- Establishing a global registry (similar to `NPM Registry` or `Scoop Main Bucket`) to provide a unified entry point for plugin distribution.
- Decomposing the existing plugin repository into individual repositories, one for each plugin.
- [X] Allowing the switching of registry addresses.
- [X] Plugin capabilities: Parsing legacy configuration files, such as `.nvmrc`, `.node-version`, `.sdkmanrc`, etc.
- [x] Allowing the switching of registry addresses.
- [x] Plugin capabilities: Parsing legacy configuration files, such as `.nvmrc`, `.node-version`, `.sdkmanrc`, etc.
- [ ] Plugin capabilities: Allowing plugins to load installed runtimes and provide information about the runtime.

## Available Plugins
Expand Down Expand Up @@ -126,7 +128,6 @@ Plugin Contributions, please go to [Public Registry](https://github.com/version-

## Thanks


> Thanks JetBrains for the free open source license. :)

<a href="https://www.jetbrains.com/?from=gev" target="_blank">
Expand All @@ -139,4 +140,3 @@ Plugin Contributions, please go to [Public Registry](https://github.com/version-

[Apache 2.0 license](./LICENSE) - Copyright (C) 2024 Han Li
and [contributors](https://github.com/version-fox/vfox/graphs/contributors)

30 changes: 7 additions & 23 deletions cmd/commands/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"strings"
"text/template"

"github.com/version-fox/vfox/internal/toolset"

"github.com/version-fox/vfox/internal"

"github.com/urfave/cli/v2"
Expand All @@ -46,26 +44,7 @@ func activateCmd(ctx *cli.Context) error {
manager := internal.NewSdkManager()
defer manager.Close()

workToolVersion, err := toolset.NewToolVersion(manager.PathMeta.WorkingDirectory)
if err != nil {
return err
}

if err = manager.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return err
}
homeToolVersion, err := toolset.NewToolVersion(manager.PathMeta.HomePath)
if err != nil {
return err
}
sdkEnvs, err := manager.EnvKeys(toolset.MultiToolVersions{
workToolVersion,
homeToolVersion,
}, internal.ShellLocation)
sdkEnvs, err := manager.FullEnvKeys()
if err != nil {
return err
}
Expand All @@ -91,7 +70,12 @@ func activateCmd(ctx *cli.Context) error {
return fmt.Errorf("unknown target shell %s", name)
}
exportStr := s.Export(exportEnvs)
str, err := s.Activate()
str, err := s.Activate(
shell.ActivateConfig{
SelfPath: path,
Args: ctx.Args().Tail(),
},
)
if err != nil {
return err
}
Expand Down
84 changes: 17 additions & 67 deletions cmd/commands/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ package commands
import (
"encoding/json"
"fmt"

"github.com/urfave/cli/v2"
"github.com/version-fox/vfox/internal"
"github.com/version-fox/vfox/internal/cache"
"github.com/version-fox/vfox/internal/env"
"github.com/version-fox/vfox/internal/logger"
"github.com/version-fox/vfox/internal/shell"
"github.com/version-fox/vfox/internal/toolset"
"path/filepath"
)

var Env = &cli.Command{
Expand All @@ -47,6 +45,10 @@ var Env = &cli.Command{
Aliases: []string{"j"},
Usage: "output json format",
},
&cli.BoolFlag{
Name: "full",
Usage: "output full env",
},
},
Action: envCmd,
Category: CategorySDK,
Expand All @@ -57,8 +59,10 @@ func envCmd(ctx *cli.Context) error {
return outputJSON()
} else if ctx.IsSet("cleanup") {
return cleanTmp()
} else if ctx.IsSet("full") {
return envFlag(ctx, "full")
} else {
return envFlag(ctx)
return envFlag(ctx, "cwd")
}
}

Expand Down Expand Up @@ -109,7 +113,7 @@ func cleanTmp() error {
return nil
}

func envFlag(ctx *cli.Context) error {
func envFlag(ctx *cli.Context, mode string) error {
shellName := ctx.String("shell")
if shellName == "" {
return cli.Exit("shell name is required", 1)
Expand All @@ -120,13 +124,19 @@ func envFlag(ctx *cli.Context) error {
}
manager := internal.NewSdkManager()
defer manager.Close()
var sdkEnvs internal.SdkEnvs
var err error
if mode == "full" {
sdkEnvs, err = manager.FullEnvKeys()
} else {
sdkEnvs, err = manager.AggregateEnvKeys()
}

sdkEnvs, err := aggregateEnvKeys(manager)
if err != nil {
return err
}

if len(sdkEnvs) == 0 && shellName != "nushell" {
if len(sdkEnvs) == 0 {
return nil
}

Expand All @@ -145,63 +155,3 @@ func envFlag(ctx *cli.Context) error {
fmt.Println(exportStr)
return nil
}

func aggregateEnvKeys(manager *internal.Manager) (internal.SdkEnvs, error) {
workToolVersion, err := toolset.NewToolVersion(manager.PathMeta.WorkingDirectory)
if err != nil {
return nil, err
}

if err = manager.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return nil, err
}

curToolVersion, err := toolset.NewToolVersion(manager.PathMeta.CurTmpPath)
if err != nil {
return nil, err
}
defer curToolVersion.Save()

// Add the working directory to the first
tvs := toolset.MultiToolVersions{workToolVersion, curToolVersion}

flushCache, err := cache.NewFileCache(filepath.Join(manager.PathMeta.CurTmpPath, "flush_env.cache"))
if err != nil {
return nil, err
}
defer flushCache.Close()

var sdkEnvs []*internal.SdkEnv

tvs.FilterTools(func(name, version string) bool {
if lookupSdk, err := manager.LookupSdk(name); err == nil {
vv, ok := flushCache.Get(name)
if ok && string(vv) == version {
logger.Debugf("Hit cache, skip flush environment, %s@%s\n", name, version)
return true
} else {
logger.Debugf("No hit cache, name: %s cache: %s, expected: %s \n", name, string(vv), version)
}
v := internal.Version(version)
if keys, err := lookupSdk.EnvKeys(v, internal.ShellLocation); err == nil {
flushCache.Set(name, cache.Value(version), cache.NeverExpired)

sdkEnvs = append(sdkEnvs, &internal.SdkEnv{
Sdk: lookupSdk, Env: keys,
})

// If we encounter a .tool-versions file, it is valid for the entire shell session,
// unless we encounter the next .tool-versions file or manually switch to the use command.
curToolVersion.Record[name] = version
return true
}
}
return false
})

return sdkEnvs, nil
}
2 changes: 1 addition & 1 deletion docs/guides/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ y
::: details Nushell

```shell
vfox activate nushell | save --append $nu.config-path
vfox activate nushell $nu.default-config-dir | save --append $nu.config-path
```

:::
Expand Down
84 changes: 84 additions & 0 deletions internal/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/mitchellh/go-ps"
"github.com/pterm/pterm"
"github.com/urfave/cli/v2"
"github.com/version-fox/vfox/internal/cache"
"github.com/version-fox/vfox/internal/config"
"github.com/version-fox/vfox/internal/env"
"github.com/version-fox/vfox/internal/logger"
Expand Down Expand Up @@ -69,6 +70,89 @@ type Manager struct {
Config *config.Config
}

func (m *Manager) FullEnvKeys() (SdkEnvs, error) {
workToolVersion, err := toolset.NewToolVersion(m.PathMeta.WorkingDirectory)
if err != nil {
return nil, err
}

if err = m.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return nil, err
}
homeToolVersion, err := toolset.NewToolVersion(m.PathMeta.HomePath)
if err != nil {
return nil, err
}
return m.EnvKeys(toolset.MultiToolVersions{
workToolVersion,
homeToolVersion,
}, ShellLocation)
}

func (m *Manager) AggregateEnvKeys() (SdkEnvs, error) {
workToolVersion, err := toolset.NewToolVersion(m.PathMeta.WorkingDirectory)
if err != nil {
return nil, err
}

if err = m.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return nil, err
}

curToolVersion, err := toolset.NewToolVersion(m.PathMeta.CurTmpPath)
if err != nil {
return nil, err
}
defer curToolVersion.Save()

// Add the working directory to the first
tvs := toolset.MultiToolVersions{workToolVersion, curToolVersion}

flushCache, err := cache.NewFileCache(filepath.Join(m.PathMeta.CurTmpPath, "flush_env.cache"))
if err != nil {
return nil, err
}
defer flushCache.Close()

var sdkEnvs []*SdkEnv

tvs.FilterTools(func(name, version string) bool {
if lookupSdk, err := m.LookupSdk(name); err == nil {
vv, ok := flushCache.Get(name)
if ok && string(vv) == version {
logger.Debugf("Hit cache, skip flush environment, %s@%s\n", name, version)
return true
} else {
logger.Debugf("No hit cache, name: %s cache: %s, expected: %s \n", name, string(vv), version)
}
v := Version(version)
if keys, err := lookupSdk.EnvKeys(v, ShellLocation); err == nil {
flushCache.Set(name, cache.Value(version), cache.NeverExpired)

sdkEnvs = append(sdkEnvs, &SdkEnv{
Sdk: lookupSdk, Env: keys,
})

// If we encounter a .tool-versions file, it is valid for the entire shell session,
// unless we encounter the next .tool-versions file or manually switch to the use command.
curToolVersion.Record[name] = version
return true
}
}
return false
})

return sdkEnvs, nil
}

func (m *Manager) EnvKeys(tvs toolset.MultiToolVersions, location Location) (SdkEnvs, error) {
var sdkEnvs SdkEnvs
tools := make(map[string]struct{})
Expand Down
2 changes: 1 addition & 1 deletion internal/shell/bash.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type bash struct{}

var Bash = bash{}

func (b bash) Activate() (string, error) {
func (b bash) Activate(config ActivateConfig) (string, error) {
return bashHook, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/shell/clink.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type clink struct{}

var Clink = clink{}

func (b clink) Activate() (string, error) {
func (b clink) Activate(config ActivateConfig) (string, error) {
return clinkHook, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/shell/fish.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function cleanup_on_exit --on-process-exit %self
end;
`

func (sh fish) Activate() (string, error) {
func (sh fish) Activate(config ActivateConfig) (string, error) {
return fishHook, nil
}

Expand Down
Loading
Loading