From 367ffa8e801c03c0e77bf154b2eb66734cbbfb70 Mon Sep 17 00:00:00 2001 From: Andrew Mayorov Date: Tue, 27 Feb 2024 23:41:50 +0100 Subject: [PATCH] feat(utils-fs): add function to compute relpaths naively --- apps/emqx_utils/src/emqx_utils_fs.erl | 23 ++++++++++++ apps/emqx_utils/test/emqx_utils_fs_SUITE.erl | 38 ++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/apps/emqx_utils/src/emqx_utils_fs.erl b/apps/emqx_utils/src/emqx_utils_fs.erl index 6d1bfe831..5c8b5ded0 100644 --- a/apps/emqx_utils/src/emqx_utils_fs.erl +++ b/apps/emqx_utils/src/emqx_utils_fs.erl @@ -20,6 +20,7 @@ -export([traverse_dir/3]). -export([read_info/1]). +-export([find_relpath/2]). -export([canonicalize/1]). -type fileinfo() :: #file_info{}. @@ -62,6 +63,28 @@ traverse_dir(FoldFun, Acc, AbsPath, {error, Reason}) -> read_info(AbsPath) -> file:read_link_info(AbsPath, [{time, posix}, raw]). +-spec find_relpath(file:name(), file:name()) -> + file:name(). +find_relpath(Path, RelativeTo) -> + case + filename:pathtype(Path) =:= filename:pathtype(RelativeTo) andalso + drop_path_prefix(filename:split(Path), filename:split(RelativeTo)) + of + false -> + Path; + [] -> + "."; + RelativePath -> + filename:join(RelativePath) + end. + +drop_path_prefix([Name | T1], [Name | T2]) -> + drop_path_prefix(T1, T2); +drop_path_prefix(Path, []) -> + Path; +drop_path_prefix(_Path, _To) -> + false. + %% @doc Canonicalize a file path. %% Removes stray slashes and converts to a string. -spec canonicalize(file:name()) -> diff --git a/apps/emqx_utils/test/emqx_utils_fs_SUITE.erl b/apps/emqx_utils/test/emqx_utils_fs_SUITE.erl index 2a36f6902..704d0af24 100644 --- a/apps/emqx_utils/test/emqx_utils_fs_SUITE.erl +++ b/apps/emqx_utils/test/emqx_utils_fs_SUITE.erl @@ -143,6 +143,44 @@ t_canonicalize_non_utf8(_) -> emqx_utils_fs:canonicalize(<<128, 128, 128>>) ). +%% + +t_find_relpath(_) -> + ?assertEqual( + "d1/1", + emqx_utils_fs:find_relpath("/usr/local/nonempty/d1/1", "/usr/local/nonempty") + ). + +t_find_relpath_same(_) -> + ?assertEqual( + ".", + emqx_utils_fs:find_relpath("/usr/local/bin", "/usr/local/bin/") + ), + ?assertEqual( + ".", + emqx_utils_fs:find_relpath("/usr/local/bin/.", "/usr/local/bin") + ). + +t_find_relpath_no_prefix(_) -> + ?assertEqual( + "/usr/lib/erlang/lib", + emqx_utils_fs:find_relpath("/usr/lib/erlang/lib", "/usr/local/bin") + ). + +t_find_relpath_both_relative(_) -> + ?assertEqual( + "1/2/3", + emqx_utils_fs:find_relpath("local/nonempty/1/2/3", "local/nonempty") + ). + +t_find_relpath_different_types(_) -> + ?assertEqual( + "local/nonempty/1/2/3", + emqx_utils_fs:find_relpath("local/nonempty/1/2/3", "/usr/local/nonempty") + ). + +%% + chmod_file(File, Mode) -> {ok, FileInfo} = file:read_file_info(File), ok = file:write_file_info(File, FileInfo#file_info{mode = Mode}).