Просмотр исходного кода

feat(utils-fs): add function to compute relpaths naively

Andrew Mayorov 1 год назад
Родитель
Сommit
367ffa8e80
2 измененных файлов с 61 добавлено и 0 удалено
  1. 23 0
      apps/emqx_utils/src/emqx_utils_fs.erl
  2. 38 0
      apps/emqx_utils/test/emqx_utils_fs_SUITE.erl

+ 23 - 0
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()) ->

+ 38 - 0
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}).