Skip to content

Commit

Permalink
Add support for lts/* (#146)
Browse files Browse the repository at this point in the history
* support lts/*

* Remove redundant line

* Add test

* Slight refactor
  • Loading branch information
Schniz authored Oct 8, 2019
1 parent ada519b commit 65c6d56
Show file tree
Hide file tree
Showing 17 changed files with 183 additions and 51 deletions.
2 changes: 1 addition & 1 deletion executable/Env.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
open Fnm;

let symlinkExists = path =>
try%lwt (Lwt_unix.lstat(path) |> Lwt.map(_ => true)) {
try%lwt(Lwt_unix.lstat(path) |> Lwt.map(_ => true)) {
| _ => Lwt.return(false)
};

Expand Down
29 changes: 28 additions & 1 deletion executable/Install.re
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ let main = (~version as versionName) => {

let versionName = Versions.format(versionName);

let%lwt versionName =
switch (versionName) {
| "latest-*" =>
switch%lwt (VersionListingLts.getLatest()) {
| Error(err) =>
raise(VersionListingLts.Problem_with_finding_latest_lts(err))
| Ok({VersionListingLts.lts, _}) =>
Printf.sprintf("latest-%s", lts) |> Lwt.return
}
| _ => Lwt.return(versionName)
};

Logger.debug(
<Pastel>
"Looking for node "
Expand Down Expand Up @@ -115,7 +127,7 @@ let main = (~version as versionName) => {
};

let run = (~version) =>
try%lwt (main(~version)) {
try%lwt(main(~version)) {
| Versions.No_Download_For_System(os, arch) =>
Logger.error(
<Pastel>
Expand All @@ -137,4 +149,19 @@ let run = (~version) =>
</Pastel>,
);
exit(1);
| VersionListingLts.Problem_with_finding_latest_lts(
VersionListingLts.Cant_find_latest_lts,
) =>
Logger.error(<Pastel color=Pastel.Red> "Can't find latest LTS" </Pastel>);
exit(1);
| VersionListingLts.Problem_with_finding_latest_lts(
VersionListingLts.Cant_parse_remote_version_listing(reason),
) =>
Logger.error(
<Pastel color=Pastel.Red>
"Can't parse json of the response:\n"
reason
</Pastel>,
);
exit(1);
};
4 changes: 2 additions & 2 deletions executable/ListLocal.re
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ let main = () =>
Versions.Local.(
{
let%lwt versions =
try%lwt (Versions.getInstalledVersions()) {
try%lwt(Versions.getInstalledVersions()) {
| _ => Lwt.fail(Cant_read_local_versions)
}
and currentVersion = Versions.getCurrentVersion();
Expand Down Expand Up @@ -36,7 +36,7 @@ let main = () =>
);

let run = () =>
try%lwt (main()) {
try%lwt(main()) {
| Cant_read_local_versions =>
Console.log("No versions installed!") |> Lwt.return
};
22 changes: 18 additions & 4 deletions executable/Use.re
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,26 @@ let error = (~quiet, arg) =>
Logger.error(arg);
};

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);
};

let switchVersion = (~version, ~quiet) => {
open Lwt.Infix;
let info = info(~quiet);
let debug = debug(~quiet);
let%lwt parsedVersion =
Versions.parse(version) >>= Opt.toLwt(Version_Not_Installed(version));
let%lwt parsedVersion = getVersion(version);

let%lwt versionPath =
switch (parsedVersion) {
Expand Down Expand Up @@ -102,7 +116,7 @@ let rec askIfInstall = (~version, ~quiet, retry) => {
};

let rec run = (~version, ~quiet) =>
try%lwt (main(~version, ~quiet)) {
try%lwt(main(~version, ~quiet)) {
| Version_Not_Installed(versionString) =>
error(
~quiet,
Expand Down
1 change: 1 addition & 0 deletions feature_tests/latest-lts/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lts/*
10 changes: 10 additions & 0 deletions feature_tests/latest-lts/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

set -e

eval "$(fnm env --multi)"

fnm install
fnm use

fnm ls | grep latest-
2 changes: 1 addition & 1 deletion feature_tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ rm -rf $TEMP_DIR_BASE
mkdir $TEMP_DIR_BASE $TEMP_BINARY_PATH
cp $BINARY $TEMP_BINARY_PATH/fnm

for test_file in $DIRECTORY/*/run.sh; do
for test_file in $DIRECTORY/latest-lts/run.sh; do
rm -rf $TEMP_FNM_DIR

echo "Running test in $test_file"
Expand Down
2 changes: 1 addition & 1 deletion library/Dotfiles.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ exception Version_Not_Provided;
exception Conflicting_Dotfiles_Found(string, string);

let versionString = fileName => {
try%lwt (
try%lwt(
Lwt_io.lines_of_file(fileName)
|> Lwt_stream.to_list
|> Lwt.map(List.hd)
Expand Down
6 changes: 3 additions & 3 deletions library/Fs.re
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let readdir = dir => {
};

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

Expand All @@ -33,13 +33,13 @@ let writeFile = (path, contents) => {
};

let exists = path => {
try%lwt (Lwt_unix.file_exists(path)) {
try%lwt(Lwt_unix.file_exists(path)) {
| Unix.Unix_error(_, _, _) => Lwt.return(false)
};
};

let readlink = path =>
try%lwt (Lwt_unix.readlink(path) |> Lwt.map(x => Ok(x))) {
try%lwt(Lwt_unix.readlink(path) |> Lwt.map(x => Ok(x))) {
| err => Lwt.return_error(err)
};

Expand Down
48 changes: 26 additions & 22 deletions library/Path.re
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ let lex = s => {
prevEsc.contents = ch === '\\' && !prevEsc.contents;
};
let rev =
j.contents === len - 1 ?
revTokens.contents :
[
j.contents === len - 1
? revTokens.contents
: [
makeToken(String.sub(s, j.contents + 1, len - 1 - j.contents)),
...revTokens.contents,
];
Expand Down Expand Up @@ -256,10 +256,14 @@ let relativeExn = s =>
* Relates two positive integers to zero and eachother.
*/
type ord =
| /** 0 === i === j */ Zeros
| /** 0 === i < j */ ZeroPositive
| /** i > 0 === j */ PositiveZero
| /** 0 < i && 0 < j */ Positives;
| /** 0 === i === j */
Zeros
| /** 0 === i < j */
ZeroPositive
| /** i > 0 === j */
PositiveZero
| /** 0 < i && 0 < j */
Positives;

/**
* Using `ord` allows us to retain exhaustiveness pattern matching checks that
Expand All @@ -268,8 +272,8 @@ type ord =
* it isn't inferred to be polymorphic.
*/
let ord = (i: int, j: int) =>
i === 0 && j === 0 ?
Zeros : i === 0 ? ZeroPositive : j === 0 ? PositiveZero : Positives;
i === 0 && j === 0
? Zeros : i === 0 ? ZeroPositive : j === 0 ? PositiveZero : Positives;

let rec repeat = (soFar, i, s) =>
i === 0 ? soFar : repeat(soFar ++ s, i - 1, s);
Expand Down Expand Up @@ -334,22 +338,22 @@ let relativizeExn: type k. (~source: t(k), ~dest: t(k)) => t(relative) =
| (Some(_), None) => raiseDriveMismatch(source, dest)
| (None, Some(_)) => raiseDriveMismatch(source, dest)
| (Some(d1), Some(d2)) =>
String.compare(d1, d2) !== 0 ?
raiseDriveMismatch(source, dest) :
relativizeDepth((0, List.rev(s1)), (0, List.rev(s2)))
String.compare(d1, d2) !== 0
? raiseDriveMismatch(source, dest)
: relativizeDepth((0, List.rev(s1)), (0, List.rev(s2)))
}
| ((Rel(w1, r1), s1), (Rel(w2, r2), s2)) =>
w1 === w2 ?
relativizeDepth((r1, List.rev(s1)), (r2, List.rev(s2))) :
raiseDriveMismatch(source, dest)
w1 === w2
? relativizeDepth((r1, List.rev(s1)), (r2, List.rev(s2)))
: raiseDriveMismatch(source, dest)
};
(Rel(Any, depth), List.rev(segs));
};

let relativize:
type k. (~source: t(k), ~dest: t(k)) => result(t(relative), exn) =
(~source, ~dest) =>
try (Ok(relativizeExn(~source, ~dest))) {
try(Ok(relativizeExn(~source, ~dest))) {
| Invalid_argument(_) as e => Error(e)
};

Expand Down Expand Up @@ -413,9 +417,9 @@ let rec join: type k1 k2. (t(k1), t(k2)) => t(k1) =
switch (p1, p2) {
| ((Rel(w, r1), []), (Rel(Any, r2), s2)) => (Rel(w, r1 + r2), s2)
| ((Rel(w, r1), [s1hd, ...s1tl] as s1), (Rel(Any, r2), s2)) =>
r2 > 0 ?
join((Rel(w, r1), s1tl), (Rel(Any, r2 - 1), s2)) :
(Rel(w, r1), List.append(s2, s1))
r2 > 0
? join((Rel(w, r1), s1tl), (Rel(Any, r2 - 1), s2))
: (Rel(w, r1), List.append(s2, s1))
| ((b1, s1), (Rel(Home, r2), s2)) =>
join((b1, [homeChar, ...List.append(s2, s1)]), (Rel(Any, r2), s2))
| ((b1, s1), (Abs(Some(ll)), s2)) => (
Expand All @@ -425,9 +429,9 @@ let rec join: type k1 k2. (t(k1), t(k2)) => t(k1) =
| ((b1, s1), (Abs(None), s2)) => (b1, List.append(s2, s1))
| ((Abs(_) as d, []), (Rel(Any, r2), s2)) => (d, s2)
| ((Abs(_) as d, [s1hd, ...s1tl] as s1), (Rel(Any, r2), s2)) =>
r2 > 0 ?
join((d, s1tl), (Rel(Any, r2 - 1), s2)) :
(d, List.append(s2, s1))
r2 > 0
? join((d, s1tl), (Rel(Any, r2 - 1), s2))
: (d, List.append(s2, s1))
};

let dirName: type k1. t(k1) => t(k1) =
Expand Down
12 changes: 12 additions & 0 deletions library/Result.re
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ let bind = (fn, res) =>
| Error(_) as e => e
};

let bind_err = (fn, res) =>
switch (res) {
| Ok(_) as o => o
| Error(x) => fn(x)
};

let bind_err_lwt = (fn, res) =>
switch (res) {
| Ok(o) => Lwt.return_ok(o)
| Error(x) => fn(x)
};

let fold = (error, ok, res) =>
switch (res) {
| Ok(x) => ok(x)
Expand Down
2 changes: 1 addition & 1 deletion library/System.re
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ module NodeArch = {
switch (Sys.os_type) {
| "Unix" =>
let%lwt result = unix_exec("uname", ~args=[|"-a"|]);
try (result |> findArches |> Lwt.return) {
try(result |> findArches |> Lwt.return) {
| _ => Lwt.fail_with("Error getting unix information")
};
| _ => Lwt.return(Other)
Expand Down
34 changes: 34 additions & 0 deletions library/VersionListing.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
type item = {
version: string,
date: string,
files: list(string),
lts: option(string),
};

let item_of_yojson = (json: Yojson.Safe.t) => {
open Yojson.Safe.Util;
let version = json |> member("version") |> to_string;
let files = json |> member("files") |> to_list |> List.map(to_string);
let date = json |> member("date") |> to_string;
let lts =
Base.Option.try_with(() => {
json |> member("lts") |> to_string |> String.lowercase_ascii
});
Ok({version, date, files, lts});
};

[@deriving of_yojson({strict: false})]
type t = list(item);

let parseVersionListing = body => {
Base.Result.try_with(() => Yojson.Safe.from_string(body))
|> Base.Result.map_error(~f=Printexc.to_string)
|> Base.Result.bind(~f=x => of_yojson(x));
};

let fromHttp = () => {
let url =
Config.FNM_NODE_DIST_MIRROR.get() |> Printf.sprintf("%s/index.json");
let%lwt {Http.body, _} = Http.makeRequest(url);
parseVersionListing(body) |> Lwt.return;
};
29 changes: 29 additions & 0 deletions library/VersionListingLts.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
type item = {
version: string,
lts: string,
};

let item_to_lts = (item: VersionListing.item) => {
item.lts |> Base.Option.map(~f=lts => {lts, version: item.version});
};

type get_latest_lts_errors =
| Cant_parse_remote_version_listing(string)
| Cant_find_latest_lts;

exception Problem_with_finding_latest_lts(get_latest_lts_errors);

let getLatest = () => {
let%lwt versions = VersionListing.fromHttp();
versions
|> Base.Result.map_error(~f=err => Cant_parse_remote_version_listing(err))
|> Base.Result.bind(~f=parsed => {
parsed
|> Base.List.filter_map(~f=item_to_lts)
|> Base.List.max_elt(~compare=(a, b) =>
Versions.compare(a.version, b.version)
)
|> Base.Result.of_option(~error=Cant_find_latest_lts)
})
|> Lwt.return;
};
Loading

0 comments on commit 65c6d56

Please sign in to comment.