diff options
Diffstat (limited to 'src/rebar_file_utils.erl')
-rw-r--r-- | src/rebar_file_utils.erl | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index 732d83f..ea1a6a2 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -37,7 +37,9 @@ system_tmpdir/0, system_tmpdir/1, reset_dir/1, - touch/1]). + touch/1, + path_from_ancestor/2, + canonical_path/1]). -include("rebar.hrl"). @@ -244,6 +246,31 @@ touch(Path) -> ok = file:write_file_info(Path, A#file_info{mtime = calendar:local_time(), atime = calendar:local_time()}). +%% for a given path return the path relative to a base directory +-spec path_from_ancestor(string(), string()) -> {ok, string()} | {error, badparent}. + +path_from_ancestor(Target, To) -> + path_from_ancestor_(filename:split(canonical_path(Target)), + filename:split(canonical_path(To))). + +path_from_ancestor_([Part|Target], [Part|To]) -> path_from_ancestor_(Target, To); +path_from_ancestor_([], []) -> {ok, ""}; +path_from_ancestor_(Target, []) -> {ok, filename:join(Target)}; +path_from_ancestor_(_, _) -> {error, badparent}. + + +%% reduce a filepath by removing all incidences of `.' and `..' +-spec canonical_path(string()) -> string(). + +canonical_path(Dir) -> canonical_path([], filename:split(filename:absname(Dir))). + +canonical_path([], []) -> filename:nativename("/"); +canonical_path(Acc, []) -> filename:join(lists:reverse(Acc)); +canonical_path(Acc, ["."|Rest]) -> canonical_path(Acc, Rest); +canonical_path([_|Acc], [".."|Rest]) -> canonical_path(Acc, Rest); +canonical_path([], [".."|Rest]) -> canonical_path([], Rest); +canonical_path(Acc, [Component|Rest]) -> canonical_path([Component|Acc], Rest). + %% =================================================================== %% Internal functions %% =================================================================== |