-
Notifications
You must be signed in to change notification settings - Fork 426
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
fnm exec
to run commands with the fnm environment (#194)
Adds `fnm exec` to run a shell executable with the current node version (or a custom one provided): ``` fnm exec -- node -v # will print the current Node version in fnm fnm exec --using 12 -- node -v # will print the version of the latest node 12 installed fnm exec --using-file -- node -v # will print the version of the current directory's node version (based on `.nvmrc` or `.node-version`) ```
- Loading branch information
Showing
9 changed files
with
202 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
open Fnm; | ||
|
||
exception System_Version_Not_Supported; | ||
exception Ambiguous_Arguments; | ||
|
||
let startsWith = (~prefix, str) => | ||
Base.String.prefix(str, String.length(prefix)) != prefix; | ||
|
||
let unsafeRun = (~cmd, ~version as maybeVersion, ~useFileVersion) => { | ||
let%lwt version = | ||
switch (maybeVersion, useFileVersion) { | ||
| (None, false) => Lwt.return_none | ||
| (Some(_), true) => Lwt.fail(Ambiguous_Arguments) | ||
| (None, true) => Fnm.Dotfiles.getVersion() |> Lwt.map(x => Some(x)) | ||
| (Some(version), false) => Lwt.return_some(version) | ||
}; | ||
let%lwt currentVersion = | ||
switch (version) { | ||
| None => Lwt.return(Directories.currentVersion) | ||
| Some(version) => | ||
let%lwt matchingVersion = LocalVersionResolver.getVersion(version); | ||
let matchingVersionPath = | ||
switch (matchingVersion) { | ||
| Alias(path) => Versions.Aliases.toDirectory(path) | ||
| Local(path) => Versions.Local.toDirectory(path) | ||
| System => raise(System_Version_Not_Supported) | ||
}; | ||
Lwt.return(matchingVersionPath); | ||
}; | ||
let fnmPath = Filename.concat(currentVersion, "bin"); | ||
let path = Opt.(Sys.getenv_opt("PATH") or ""); | ||
let pathEnv = Printf.sprintf("PATH=%s:%s", fnmPath, path); | ||
let cmd = cmd |> Array.copy |> Array.append([|"env", pathEnv|]); | ||
let%lwt exitCode = | ||
Lwt_process.exec( | ||
~stdin=`Keep, | ||
~stdout=`Keep, | ||
~stderr=`Keep, | ||
~env=Unix.environment(), | ||
("", cmd), | ||
); | ||
|
||
switch (exitCode) { | ||
| Unix.WEXITED(0) => Lwt.return_ok() | ||
| Unix.WEXITED(x) | ||
| Unix.WSTOPPED(x) | ||
| Unix.WSIGNALED(x) => Lwt.return_error(x) | ||
}; | ||
}; | ||
|
||
let run = (~cmd, ~version, ~useFileVersion) => { | ||
try%lwt(unsafeRun(~cmd, ~version, ~useFileVersion)) { | ||
| Ambiguous_Arguments => | ||
Console.error( | ||
<Pastel color=Pastel.Red> | ||
<Pastel bold=true> "Error: " </Pastel> | ||
"You passed both " | ||
<Pastel color=Pastel.Cyan> "--using" </Pastel> | ||
" and " | ||
<Pastel color=Pastel.Cyan> "--using-file" </Pastel> | ||
".\n" | ||
"Please provide only one of them." | ||
</Pastel>, | ||
); | ||
Lwt.return_error(1); | ||
| System_Version_Not_Supported => | ||
Console.error( | ||
<Pastel color=Pastel.Red> | ||
<Pastel bold=true> "Error: " </Pastel> | ||
"System version is not supported in " | ||
<Pastel color=Pastel.Yellow> "`fnm exec`" </Pastel> | ||
</Pastel>, | ||
); | ||
Lwt.return_error(1); | ||
| LocalVersionResolver.Version_Not_Installed(versionName) => | ||
Console.error( | ||
<Pastel color=Pastel.Red> | ||
<Pastel bold=true> "Error: " </Pastel> | ||
"Version " | ||
<Pastel color=Pastel.Cyan> versionName </Pastel> | ||
" is not installed." | ||
</Pastel>, | ||
); | ||
Lwt.return_error(1); | ||
| Dotfiles.Version_Not_Provided => | ||
Console.error( | ||
<Pastel color=Pastel.Red> | ||
"No .nvmrc or .node-version file was found in the current directory. Please provide a version number." | ||
</Pastel>, | ||
); | ||
Lwt.return_error(1); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/bin/bash | ||
|
||
set -e | ||
|
||
fnm install v6.10.0 | ||
fnm install v8.10.0 | ||
fnm install v10.10.0 | ||
fnm use v8.10.0 | ||
|
||
fnm exec -- node -v | grep "v8.10.0" | ||
fnm exec --using 6 -- node -v | grep "v6.10.0" | ||
fnm exec --using 10 -- node -v | grep "v10.10.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
exception Version_Not_Installed(string); | ||
|
||
/** Parse a local version, including lts and aliases */ | ||
let getVersion = version => { | ||
let%lwt parsed = Versions.parse(version); | ||
let%lwt resultWithLts = | ||
switch (parsed) { | ||
| Ok(x) => Lwt.return_ok(x) | ||
| Error("latest-*") => | ||
switch%lwt (VersionListingLts.getLatest()) { | ||
| Error(_) => Lwt.return_error(Version_Not_Installed(version)) | ||
| Ok({VersionListingLts.lts, _}) => | ||
Versions.Alias("latest-" ++ lts) |> Lwt.return_ok | ||
} | ||
| _ => Version_Not_Installed(version) |> Lwt.return_error | ||
}; | ||
resultWithLts |> Result.fold(Lwt.fail, Lwt.return); | ||
}; | ||
|
||
/** | ||
* Get matches for all versions that match a semver partial | ||
*/ | ||
let getMatchingLocalVersions = version => { | ||
open Versions.Local; | ||
|
||
let%lwt installedVersions = Versions.getInstalledVersions(); | ||
let formattedVersionName = Versions.format(version); | ||
|
||
let matchingVersions = | ||
installedVersions | ||
|> List.filter(v => | ||
Versions.isVersionFitsPrefix(formattedVersionName, v.name) | ||
|| v.name == formattedVersionName | ||
) | ||
|> List.sort((a, b) => - compare(a.name, b.name)); | ||
|
||
Lwt.return(matchingVersions); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters