Skip to content

Commit

Permalink
Added aliases (Fixes #29) and opt-in multishell support (Fixes #19)
Browse files Browse the repository at this point in the history
  • Loading branch information
Schniz committed Feb 12, 2019
1 parent 771d4d3 commit b9de250
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 51 deletions.
8 changes: 1 addition & 7 deletions executable/Alias.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
open Fnm;

let lwtIgnore = lwt => Lwt.catch(() => lwt, _ => Lwt.return());

let run = (~name, ~version) => {
let version = Versions.format(version);
let versionPath = Filename.concat(Directories.nodeVersions, version);
Expand All @@ -26,11 +24,7 @@ let run = (~name, ~version) => {
</Pastel>,
);

let aliasPath = Filename.concat(Directories.aliases, name);

let%lwt _ = System.mkdirp(Directories.aliases);
let%lwt _ = Lwt_unix.unlink(aliasPath) |> lwtIgnore;
let%lwt _ = Lwt_unix.symlink(versionPath, aliasPath);
let%lwt () = Versions.Aliases.set(~alias=name, ~versionPath);

Lwt.return();
};
18 changes: 13 additions & 5 deletions executable/Env.re
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
open Fnm;

let rec getTempFileName = () => {
let rec makeTemporarySymlink = () => {
let suggestedName =
Filename.concat(
Filename.get_temp_dir_name(),
Expand All @@ -11,24 +11,32 @@ let rec getTempFileName = () => {
let%lwt exists = Lwt_unix.file_exists(suggestedName);

if (exists) {
getTempFileName();
makeTemporarySymlink();
} else {
let%lwt _ =
Lwt_unix.symlink(
suggestedName,
Filename.concat(Directories.defaultVersion, "installation"),
);
Lwt.return(suggestedName);
};
};

let run = (~shell, ~multishell) => {
open Lwt;

let%lwt path =
multishell
? getTempFileName() : Lwt.return(Directories.globalCurrentVersion);
? makeTemporarySymlink() : Lwt.return(Directories.globalCurrentVersion);

switch (shell) {
| System.Shell.Bash =>
Printf.sprintf("export PATH=%s/bin:$PATH", path) |> Console.log;
Printf.sprintf("export FNM_MULTISHELL_PATH=%s", path) |> Console.log;
| System.Shell.Fish =>
Printf.sprintf("set PATH %s/bin $PATH", path) |> Console.log;
Printf.sprintf("set FNM_MULTISHELL_PATH %s", path) |> Console.log;
Printf.sprintf("set -e FNM_MULTISHELL_PATH;") |> Console.log;
Printf.sprintf("set -x PATH %s/bin $PATH;", path) |> Console.log;
Printf.sprintf("set -x FNM_MULTISHELL_PATH %s;", path) |> Console.log;
};

Lwt.return();
Expand Down
9 changes: 7 additions & 2 deletions executable/FnmApp.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
let version = Fnm.Fnm__Package.version;

module Commands = {
let use = version => Lwt_main.run(Use.run(~version));
let use = (version, quiet) => Lwt_main.run(Use.run(~version, ~quiet));
let alias = (version, name) => Lwt_main.run(Alias.run(~name, ~version));
let listRemote = () => Lwt_main.run(ListRemote.run());
let listLocal = () => Lwt_main.run(ListLocal.run());
Expand Down Expand Up @@ -78,6 +78,11 @@ let use = {
let doc = "Switch to another installed node version";
let man = [];

let quiet = {
let doc = "Don't print stuff";
Arg.(value & flag & info(["quiet"], ~doc));
};

let selectedVersion = {
let doc = "Switch to version $(docv).\nLeave empty to look for value from `.nvmrc`";
Arg.(
Expand All @@ -86,7 +91,7 @@ let use = {
};

(
Term.(const(Commands.use) $ selectedVersion),
Term.(const(Commands.use) $ selectedVersion $ quiet),
Term.info("use", ~version, ~doc, ~exits=Term.default_exits, ~man),
);
};
Expand Down
17 changes: 12 additions & 5 deletions executable/ListLocal.re
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,29 @@ let main = () =>
Versions.Local.(
{
let%lwt versions =
Versions.getInstalledVersions()
|> Result.mapError(_ => Cant_read_local_versions)
|> Result.toLwtErr;
try%lwt (Versions.getInstalledVersions()) {
| _ => Lwt.fail(Cant_read_local_versions)
};
let currentVersion = Versions.getCurrentVersion();

Console.log("The following versions are installed:");

versions
|> Array.iter(version => {
|> List.iter(version => {
let color =
switch (currentVersion) {
| None => None
| Some(x) when x.name == version.name => Some(Pastel.Cyan)
| Some(_) => None
};
Console.log(<Pastel ?color> "* " {version.name} </Pastel>);
let aliases =
List.length(version.aliases) === 0
? ""
: Printf.sprintf(
" (%s)",
version.aliases |> String.concat(", "),
);
Console.log(<Pastel ?color> "* " {version.name} aliases </Pastel>);
});

Lwt.return();
Expand Down
49 changes: 34 additions & 15 deletions executable/Use.re
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@ let lwtIgnore = lwt => Lwt.catch(() => lwt, _ => Lwt.return());

exception Version_Not_Installed(string);

let switchVersion = version => {
let versionDir = Filename.concat(Directories.nodeVersions, version);
let log = (~quiet, arg) =>
if (!quiet) {
Console.log(arg);
};

let%lwt _ =
if%lwt (Lwt_unix.file_exists(versionDir) |> Lwt.map(x => !x)) {
Lwt.fail(Version_Not_Installed(version));
let switchVersion = (~version, ~quiet) => {
open Lwt;
let log = log(~quiet);
let%lwt parsedVersion =
Versions.parse(version) >>= Opt.toLwt(Version_Not_Installed(version));

let%lwt versionPath =
switch (parsedVersion) {
| Local(version) => Versions.Local.toDirectory(version) |> Lwt.return
| Alias(alias) => Versions.Aliases.toDirectory(alias) |> Lwt.return
};

let destination = Filename.concat(versionDir, "installation");
let destination = Filename.concat(versionPath, "installation");
let source = Directories.currentVersion;

Console.log(
log(
<Pastel>
"Linking "
<Pastel color=Pastel.Cyan> source </Pastel>
Expand All @@ -25,36 +34,46 @@ let switchVersion = version => {
);

let%lwt _ = Lwt_unix.unlink(Directories.currentVersion) |> lwtIgnore;
let%lwt _ = Lwt_unix.symlink(destination, Directories.currentVersion);
let%lwt _ = Lwt_unix.symlink(destination, Directories.currentVersion)
and defaultAliasExists = Lwt_unix.file_exists(Directories.defaultVersion);

let%lwt _ =
if (!defaultAliasExists) {
Versions.Aliases.set(~alias="default", ~versionPath=destination);
} else {
Lwt.return();
};

Console.log(
log(
<Pastel> "Using " <Pastel color=Pastel.Cyan> version </Pastel> </Pastel>,
);

Lwt.return();
};

let main = (~version as providedVersion) => {
let main = (~version as providedVersion, ~quiet) => {
let%lwt version =
switch (providedVersion) {
| Some(version) => Lwt.return(version)
| None => Nvmrc.getVersion()
};
switchVersion(Versions.format(version));
switchVersion(~version, ~quiet);
};

let run = (~version) =>
try%lwt (main(~version)) {
let run = (~version, ~quiet) =>
try%lwt (main(~version, ~quiet)) {
| Version_Not_Installed(version) =>
Console.log(
log(
~quiet,
<Pastel color=Pastel.Red>
"The following version is not installed: "
version
</Pastel>,
)
|> Lwt.return
| Nvmrc.Version_Not_Provided =>
Console.log(
log(
~quiet,
<Pastel color=Pastel.Red>
"No .nvmrc was found in the current directory. Please provide a version number."
</Pastel>,
Expand Down
1 change: 1 addition & 0 deletions feature_tests/fish/run.fish
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env fish

eval (fnm env --fish)

fnm install v8.11.3
fnm use v8.11.3

Expand Down
31 changes: 31 additions & 0 deletions feature_tests/multishell/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

set -e

eval $(fnm env)

fnm install v8.11.3
fnm install v11.9.0

fnm use v8.11.3

bash -c '
set -e
eval $(fnm env --multi)
fnm use v11.9.0
echo "> verifying version v11.9.0 for child bash"
if [ "$(node -v)" == "v11.9.0" ]; then
echo "Okay!"
else
echo "Node version should be v11.9.0 in the bash fork"
exit 1
fi
'

echo "> verifying version v8.11.3 for parent bash"
if [ "$(node -v)" == "v8.11.3" ]; then
echo "Okay!"
else
echo "Node version should be v8.11.3 in the base bash"
exit 1
fi
1 change: 1 addition & 0 deletions library/Directories.re
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ let currentVersion =
Opt.(Sys.getenv_opt("FNM_MULTISHELL_PATH") or globalCurrentVersion);
let downloads = Filename.concat(sfwRoot, "downloads");
let aliases = Filename.concat(sfwRoot, "aliases");
let defaultVersion = Filename.concat(aliases, "default");
4 changes: 2 additions & 2 deletions library/Http.re
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let rec getBody = listOfStrings => {
};
};

let rec getStatus = string => {
let getStatus = string => {
List.nth(String.split_on_char(' ', string), 1);
};

Expand All @@ -27,7 +27,7 @@ let verifyStatus = response => {
| 200 => Lwt.return(response)
| x when x / 100 == 4 => Lwt.fail(Not_found(response))
| x when x / 100 == 5 => Lwt.fail(Internal_server_error(response))
| x => Lwt.fail(Unknown_status_code(response))
| _ => Lwt.fail(Unknown_status_code(response))
};
};

Expand Down
6 changes: 6 additions & 0 deletions library/Opt.re
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ let toResult = (error, opt) =>
| Some(x) => Ok(x)
};

let toLwt = (error, opt) =>
switch (opt) {
| Some(x) => Lwt.return(x)
| None => Lwt.fail(error)
};

let some = x => Some(x);

let (or) = (opt, b) => fold(() => b, x => x, opt);
25 changes: 25 additions & 0 deletions library/System.re
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,28 @@ module NodeOS = {
| Linux => "linux"
| Other(_) => "other";
};

let readdir = dir => {
let items = ref([]);
let%lwt dir = Lwt_unix.opendir(dir);
let iterate = () => {
let%lwt _ =
while%lwt (true) {
let%lwt value = Lwt_unix.readdir(dir);
if (value.[0] != '.') {
items := [value, ...items^];
};
Lwt.return();
};

Lwt.return([]);
};

let%lwt items =
try%lwt (iterate()) {
| End_of_file => Lwt.return(items^)
};

let%lwt _ = Lwt_unix.closedir(dir);
Lwt.return(items);
};
Loading

0 comments on commit b9de250

Please sign in to comment.