diff options
author | Fred Hebert <mononcqc@ferd.ca> | 2015-09-25 17:46:03 -0400 |
---|---|---|
committer | Fred Hebert <mononcqc@ferd.ca> | 2015-09-25 17:46:03 -0400 |
commit | 509c7afec67a980e73efb61c53efd87a53e7e14e (patch) | |
tree | 0fdf2991408531cb475ea05cddc17d90632c9b39 /src | |
parent | 4d76a556e20665e0d3f77910635586613036fa4e (diff) | |
parent | ae275c6396545defc80a765a6b835d01f4c76599 (diff) |
Merge pull request #800 from talentdeficit/extract_path_utils
extract `retarget_path/2', `relative_path/2' and `reduce_path/1' and add tests
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar_dir.erl | 29 | ||||
-rw-r--r-- | src/rebar_file_utils.erl | 29 |
2 files changed, 56 insertions, 2 deletions
diff --git a/src/rebar_dir.erl b/src/rebar_dir.erl index 7220d89..364e197 100644 --- a/src/rebar_dir.erl +++ b/src/rebar_dir.erl @@ -23,7 +23,8 @@ make_relative_path/2, src_dirs/1, src_dirs/2, extra_src_dirs/1, extra_src_dirs/2, - all_src_dirs/1, all_src_dirs/3]). + all_src_dirs/1, all_src_dirs/3, + retarget_path/2]). -include("rebar.hrl"). @@ -160,3 +161,29 @@ all_src_dirs(Opts) -> all_src_dirs(Opts, [], []). list(file:filename_all()). all_src_dirs(Opts, SrcDefault, ExtraDefault) -> src_dirs(Opts, SrcDefault) ++ extra_src_dirs(Opts, ExtraDefault). + +%% given a path if that path is an ancestor of an app dir return the path relative to that +%% apps outdir. if the path is not an ancestor to any app dirs but is an ancestor of the +%% project root return the path relative to the project base_dir. if it is not an ancestor +%% of either return it unmodified +-spec retarget_path(rebar_state:t(), string()) -> string(). + +retarget_path(State, Path) -> + ProjectApps = rebar_state:project_apps(State), + retarget_path(State, Path, ProjectApps). + +%% not relative to any apps in project, check to see it's relative to +%% project root +retarget_path(State, Path, []) -> + case rebar_file_utils:path_from_ancestor(rebar_file_utils:canonical_path(Path), rebar_state:dir(State)) of + {ok, NewPath} -> filename:join([base_dir(State), NewPath]); + %% not relative to project root, don't modify + {error, badparent} -> Path + end; +%% relative to current app, retarget to the same dir relative to +%% the app's out_dir +retarget_path(State, Path, [App|Rest]) -> + case rebar_file_utils:path_from_ancestor(rebar_file_utils:canonical_path(Path), rebar_app_info:dir(App)) of + {ok, NewPath} -> filename:join([rebar_app_info:out_dir(App), NewPath]); + {error, badparent} -> retarget_path(State, Path, Rest) + end. 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 %% =================================================================== |