Browse Source

Infer complete semver out of partial input. (#54)

remotes/origin/add-simple-redirecting-site
Gal Schlezinger 6 years ago committed by GitHub
parent
commit
c5b5b3187e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      executable/Install.re
  2. 11
      executable/Use.re
  3. 16
      feature_tests/partial_semver/run.sh
  4. 163
      library/Versions.re

5
executable/Install.re

@ -42,8 +42,11 @@ let main = (~version as versionName) => {
</Pastel>, </Pastel>,
); );
let%lwt filepath = let%lwt (versionName, filepath) =
Versions.getFileToDownload(~version=versionName, ~os, ~arch); Versions.getFileToDownload(~version=versionName, ~os, ~arch);
let%lwt _ = Versions.throwIfInstalled(versionName);
let tarDestination = let tarDestination =
Filename.concat( Filename.concat(
Directories.downloads, Directories.downloads,

11
executable/Use.re

@ -21,6 +21,12 @@ let switchVersion = (~version, ~quiet) => {
| Alias(alias) => Versions.Aliases.toDirectory(alias) |> Lwt.return | Alias(alias) => Versions.Aliases.toDirectory(alias) |> Lwt.return
}; };
let versionName =
switch (parsedVersion) {
| Local(v) => v
| Alias(v) => v
};
let destination = Filename.concat(versionPath, "installation"); let destination = Filename.concat(versionPath, "installation");
let source = Directories.currentVersion; let source = Directories.currentVersion;
@ -45,7 +51,10 @@ let switchVersion = (~version, ~quiet) => {
}; };
log( log(
<Pastel> "Using " <Pastel color=Pastel.Cyan> version </Pastel> </Pastel>, <Pastel>
"Using "
<Pastel color=Pastel.Cyan> versionName </Pastel>
</Pastel>,
); );
Lwt.return(); Lwt.return();

16
feature_tests/partial_semver/run.sh

@ -0,0 +1,16 @@
#!/bin/bash
eval `fnm env --multi`
fnm install 6 # no new versions would be issued for this unsupported version
fnm install 8.11.3
fnm use 6
if [ "$(node -v)" != "v6.16.0" ]; then
echo "Node version mismatch: $(node -v). Expected: v6.16.0"
fi
fnm use 8
if [ "$(node -v)" != "v8.11.3" ]; then
echo "Node version mismatch: $(node -v). Expected: v8.11.3"
fi

163
library/Versions.re

@ -2,6 +2,28 @@ module VersionSet = Set.Make(String);
let lwtIgnore = lwt => Lwt.catch(() => lwt, _ => Lwt.return()); let lwtIgnore = lwt => Lwt.catch(() => lwt, _ => Lwt.return());
let flip = (fn, a, b) => fn(b, a);
let skip = (~amount, str) =>
Str.last_chars(str, String.length(str) - amount);
let parseSemver = version => version |> skip(~amount=1) |> Semver.of_string;
let compare = (v1, v2) =>
switch (parseSemver(v1), parseSemver(v2)) {
| (Some(v1), Some(v2)) => Semver.compare(v1, v2)
| (None, _)
| (_, None) => - Core.String.compare(v1, v2)
};
let isVersionFitsPrefix = (prefix, version) => {
let length = String.length(prefix);
String.length(version) >= length
+ 1
&& Str.first_chars(version, length + 1) == prefix
++ ".";
};
module Local = { module Local = {
type t = { type t = {
name: string, name: string,
@ -10,6 +32,18 @@ module Local = {
}; };
let toDirectory = name => Filename.concat(Directories.nodeVersions, name); let toDirectory = name => Filename.concat(Directories.nodeVersions, name);
let getLatestInstalledNameByPrefix = prefix => {
open Lwt;
let%lwt versions =
Fs.readdir(Directories.nodeVersions)
>|= List.filter(isVersionFitsPrefix(prefix))
>|= List.sort(flip(compare));
switch (versions) {
| [version, ...xs] => Lwt.return_some(version)
| [] => Lwt.return_none
};
};
}; };
exception Version_not_found(string); exception Version_not_found(string);
@ -79,18 +113,6 @@ module Remote = {
installed: bool, installed: bool,
}; };
let skip = (~amount, str) =>
Str.last_chars(str, String.length(str) - amount);
let parseSemver = version => version |> skip(~amount=1) |> Semver.of_string;
let compare = (v1, v2) =>
switch (parseSemver(v1), parseSemver(v2)) {
| (Some(v1), Some(v2)) => Semver.compare(v1, v2)
| (None, _)
| (_, None) => - Core.String.compare(v1, v2)
};
let getInstalledVersionSet = () => let getInstalledVersionSet = () =>
Lwt.( Lwt.(
catch(() => Fs.readdir(Directories.nodeVersions), _ => return([])) catch(() => Fs.readdir(Directories.nodeVersions), _ => return([]))
@ -142,39 +164,6 @@ let endsWith = (~suffix, str) => {
exception No_Download_For_System(System.NodeOS.t, System.NodeArch.t); exception No_Download_For_System(System.NodeOS.t, System.NodeArch.t);
let getFileToDownload = (~version as versionName, ~os, ~arch) => {
let versionName =
switch (Str.first_chars(versionName, 1) |> Int32.of_string) {
| _ => "v" ++ versionName
| exception _ => versionName
};
let url =
Printf.sprintf("%s%s/", Config.FNM_NODE_DIST_MIRROR.get(), versionName);
let%lwt html =
try%lwt (Http.makeRequest(url) |> Lwt.map(Http.body)) {
| Http.Not_found(_) => Lwt.fail(Version_not_found(versionName))
};
let filenames =
html
|> Remote.getRelativeLinksFromHTML
|> List.filter(
endsWith(
~suffix=
System.NodeOS.toString(os)
++ "-"
++ System.NodeArch.toString(arch)
++ Remote.downloadFileSuffix,
),
);
switch (filenames |> List.hd) {
| x => Lwt.return(url ++ x)
| exception _ => Lwt.fail(No_Download_For_System(os, arch))
};
};
let getCurrentVersion = () => let getCurrentVersion = () =>
switch (Fs.realpath(Directories.currentVersion)) { switch (Fs.realpath(Directories.currentVersion)) {
| installationPath => | installationPath =>
@ -187,8 +176,7 @@ let getCurrentVersion = () =>
let getInstalledVersions = () => { let getInstalledVersions = () => {
let%lwt versions = let%lwt versions =
Fs.readdir(Directories.nodeVersions) Fs.readdir(Directories.nodeVersions) |> Lwt.map(List.sort(compare))
|> Lwt.map(List.sort(Remote.compare))
and aliases = Aliases.byVersion(); and aliases = Aliases.byVersion();
versions versions
@ -216,7 +204,7 @@ let getRemoteVersions = () => {
Str.last_chars(x, 1) == "/" && Str.first_chars(x, 1) != "." Str.last_chars(x, 1) == "/" && Str.first_chars(x, 1) != "."
) )
|> Core.List.map(~f=x => Str.first_chars(x, String.length(x) - 1)) |> Core.List.map(~f=x => Str.first_chars(x, String.length(x) - 1))
|> List.sort(Remote.compare) |> List.sort(compare)
|> List.map(name => |> List.map(name =>
Remote.{ Remote.{
name, name,
@ -228,6 +216,70 @@ let getRemoteVersions = () => {
|> Lwt.return; |> Lwt.return;
}; };
let getRemoteLatestVersionByPrefix = prefix => {
open Remote;
open Lwt;
let%lwt remoteVersions = getRemoteVersions();
let compatibleVersions =
remoteVersions
|> List.map(x => x.name)
|> List.filter(isVersionFitsPrefix(prefix))
|> List.sort(flip(compare));
switch (compatibleVersions) {
| [version, ...vs] => Lwt.return_some(version)
| [] => Lwt.return_none
};
};
let getExactFileToDownload = (~version as versionName, ~os, ~arch) => {
let versionName =
switch (Str.first_chars(versionName, 1) |> Int32.of_string) {
| _ => "v" ++ versionName
| exception _ => versionName
};
let url =
Printf.sprintf("%s%s/", Config.FNM_NODE_DIST_MIRROR.get(), versionName);
let%lwt html =
try%lwt (Http.makeRequest(url) |> Lwt.map(Http.body)) {
| Http.Not_found(_) => Lwt.fail(Version_not_found(versionName))
};
let filenames =
html
|> Remote.getRelativeLinksFromHTML
|> List.filter(
endsWith(
~suffix=
System.NodeOS.toString(os)
++ "-"
++ System.NodeArch.toString(arch)
++ Remote.downloadFileSuffix,
),
);
switch (filenames |> List.hd) {
| filename =>
let nodeVersion = List.nth(String.split_on_char('-', filename), 1);
Lwt.return((nodeVersion, url ++ filename));
| exception _ => Lwt.fail(No_Download_For_System(os, arch))
};
};
let getFileToDownload = (~version, ~os, ~arch) => {
try%lwt (getExactFileToDownload(~version, ~os, ~arch)) {
| Version_not_found(_) as e =>
switch%lwt (getRemoteLatestVersionByPrefix(version)) {
| None => Lwt.fail(e)
| Some(exactVersion) =>
getExactFileToDownload(~version=exactVersion, ~os, ~arch)
}
};
};
type t = type t =
| Alias(string) | Alias(string)
| Local(string); | Local(string);
@ -238,12 +290,15 @@ let parse = version => {
let versionPath = Local.toDirectory(formattedVersion); let versionPath = Local.toDirectory(formattedVersion);
let%lwt aliasExists = Lwt_unix.file_exists(aliasPath) let%lwt aliasExists = Lwt_unix.file_exists(aliasPath)
and versionExists = Lwt_unix.file_exists(versionPath); and versionExists = Lwt_unix.file_exists(versionPath)
and versionByPrefixPath =
switch (versionExists, aliasExists) { Local.getLatestInstalledNameByPrefix(formattedVersion);
| (true, _) => Some(Local(formattedVersion)) |> Lwt.return
| (_, true) => Some(Alias(version)) |> Lwt.return switch (versionExists, aliasExists, versionByPrefixPath) {
| (false, false) => Lwt.return_none | (true, _, _) => Some(Local(formattedVersion)) |> Lwt.return
| (_, true, _) => Some(Alias(version)) |> Lwt.return
| (_, false, Some(version)) => Some(Local(version)) |> Lwt.return
| (false, false, None) => Lwt.return_none
}; };
}; };

Loading…
Cancel
Save