From c2f0d58b904c1ae94a9df1d93aef731ee1826725 Mon Sep 17 00:00:00 2001 From: Gal Schlezinger Date: Wed, 22 May 2019 20:01:50 +0300 Subject: [PATCH] Implement `realpath` instead of binding to C library (#102) drop Filename.realpath usage, for crossplatform support --- executable/ListInstallations.re | 37 ---------------------------- executable/ListLocal.re | 4 +-- executable/ListRemote.re | 4 +-- library/Fs.re | 25 +++++++++++++------ library/Versions.re | 43 +++++++++++++++------------------ 5 files changed, 42 insertions(+), 71 deletions(-) delete mode 100644 executable/ListInstallations.re diff --git a/executable/ListInstallations.re b/executable/ListInstallations.re deleted file mode 100644 index 98a1543..0000000 --- a/executable/ListInstallations.re +++ /dev/null @@ -1,37 +0,0 @@ -open Fnm; - -let colorizeVersions = (~current, ~versions) => { - let strings = - versions - |> List.map(version => { - open Versions.Local; - let str = "- " ++ version.name; - - let color = - current - |> Opt.bind(current => - current.name == version.name ? Some(Pastel.Green) : None - ); - - str ; - }); - - - "## List of installed versions:\n" - ...strings - ; -}; - -let getVersionsString = () => - Result.( - { - let%bind versions = - Versions.getInstalledVersions() |> Result.map(Array.to_list); - - let current = Versions.getCurrentVersion(); - - colorizeVersions(~current, ~versions) |> Result.return; - } - ); - -let run = () => getVersionsString() |> Result.map(Console.log) |> Lwt.return; diff --git a/executable/ListLocal.re b/executable/ListLocal.re index ed875d4..3858454 100644 --- a/executable/ListLocal.re +++ b/executable/ListLocal.re @@ -8,8 +8,8 @@ let main = () => let%lwt versions = try%lwt (Versions.getInstalledVersions()) { | _ => Lwt.fail(Cant_read_local_versions) - }; - let currentVersion = Versions.getCurrentVersion(); + } + and currentVersion = Versions.getCurrentVersion(); Console.log("The following versions are installed:"); diff --git a/executable/ListRemote.re b/executable/ListRemote.re index 0fdd11e..5ea8e0b 100644 --- a/executable/ListRemote.re +++ b/executable/ListRemote.re @@ -3,8 +3,8 @@ open Fnm; let run = () => { Console.log("Looking for some node versions upstream..."); - let%lwt versions = Versions.getRemoteVersions(); - let currentVersion = Versions.getCurrentVersion(); + let%lwt versions = Versions.getRemoteVersions() + and currentVersion = Versions.getCurrentVersion(); versions |> List.iter(version => { diff --git a/library/Fs.re b/library/Fs.re index 061c395..3843cb7 100644 --- a/library/Fs.re +++ b/library/Fs.re @@ -1,5 +1,3 @@ -open Core; - let readdir = dir => { let items = ref([]); let%lwt dir = Lwt_unix.opendir(dir); @@ -40,9 +38,22 @@ let exists = path => { }; }; -let realpath = Filename.realpath; +let readlink = path => + try%lwt (Lwt_unix.readlink(path) |> Lwt.map(x => Ok(x))) { + | err => Lwt.return_error(err) + }; -let try_readlink = path => - try (Ok(Unix.readlink(path))) { - | err => Error(err) - }; \ No newline at end of file +type path = + | Exists(string) + | Missing(string); + +let rec realpath = path => { + switch%lwt (readlink(path)) { + | Ok(path) => realpath(path) + | Error(_) => + switch%lwt (exists(path)) { + | true => Exists(path) |> Lwt.return + | false => Missing(path) |> Lwt.return + } + }; +}; diff --git a/library/Versions.re b/library/Versions.re index 707fcdf..ed6888c 100644 --- a/library/Versions.re +++ b/library/Versions.re @@ -72,19 +72,23 @@ module Aliases = { | _ => Lwt.return([]) }; aliases - |> List.map(alias => { + |> Lwt_list.map_p(alias => { let fullPath = Filename.concat(Directories.aliases, alias); - { + let%lwt realpath = + Filename.concat(Directories.aliases, alias) + |> Fs.realpath + |> Lwt.map( + fun + | Fs.Exists(x) => x + | Fs.Missing(x) => x, + ); + + Lwt.return({ name: alias, fullPath, - versionName: - Filename.concat(Directories.aliases, alias) - |> Fs.realpath - |> Filename.dirname - |> Filename.basename, - }; - }) - |> Lwt.return; + versionName: realpath |> Filename.dirname |> Filename.basename, + }); + }); }; let byVersion = () => { @@ -172,24 +176,17 @@ let endsWith = (~suffix, str) => { exception No_Download_For_System(System.NodeOS.t, System.NodeArch.t); let getCurrentVersion = () => { - switch (Fs.realpath(Directories.currentVersion)) { - | installationPath => + switch%lwt (Fs.realpath(Directories.currentVersion)) { + | Missing(x) when x == Directories.currentVersion => Lwt.return_none + | Missing(_) => Lwt.return_some(Local.systemVersion) + | Exists(installationPath) => let fullPath = Filename.dirname(installationPath); - Some( + Lwt.return_some( Local.{fullPath, name: Core.Filename.basename(fullPath), aliases: []}, ); - | exception (Unix.Unix_error(_, _, _)) => - switch (Fs.try_readlink(Directories.currentVersion)) { - | Ok(x) - when - Core.String.substr_index(x, ~pattern=Local.systemVersion.fullPath) - == Some(0) => - Some(Local.systemVersion) - | Ok(_) - | Error(_) => None - } }; }; + let getInstalledVersions = () => { let%lwt versions = Fs.readdir(Directories.nodeVersions) |> Lwt.map(List.sort(compare))