diff options
author | Juhani Rankimies <juhani@juranki.com> | 2010-10-26 07:19:30 +0300 |
---|---|---|
committer | Dave Smith <dizzyd@dizzyd.com> | 2010-10-27 11:39:12 -0600 |
commit | fd5ebe69a4d4028908247f6d669eb38254613269 (patch) | |
tree | f963d76d95a46fda14d6d491ecdc14cabcdc06c1 /src | |
parent | 75fc2378bf006b5660ce2115561d36bea10e04c5 (diff) |
Port rebar_file_utils to Windows
Modify rm_rf and cp_r to work when {win32,_} = os:type().
Simplify rm_rf to only accept one filename, directoryname or wildcard.
Add unit tests to ensure a similar behaviour on windows and unix.
Thanks to tuncer for guidance and feedback.
Diffstat (limited to 'src')
-rw-r--r-- | src/rebar_erlc_compiler.erl | 6 | ||||
-rw-r--r-- | src/rebar_file_utils.erl | 78 | ||||
-rw-r--r-- | src/rebar_reltool.erl | 2 |
3 files changed, 76 insertions, 10 deletions
diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 50e890c..e872e2b 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -71,10 +71,8 @@ compile(Config, _AppFile) -> -spec clean(Config::#config{}, AppFile::string()) -> 'ok'. clean(_Config, _AppFile) -> - %% TODO: This would be more portable if it used Erlang to traverse - %% the dir structure and delete each file; however it would also - %% much slower. - ok = rebar_file_utils:rm_rf("ebin/*.beam priv/mibs/*.bin"), + lists:foreach(fun(F) -> ok = rebar_file_utils:rm_rf(F) end, + ["ebin/*.beam", "priv/mibs/*.bin"]), YrlFiles = rebar_utils:find_files("src", "^.*\\.[x|y]rl\$"), rebar_file_utils:delete_each( diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl index 429f478..1538fa8 100644 --- a/src/rebar_file_utils.erl +++ b/src/rebar_file_utils.erl @@ -36,14 +36,30 @@ %% Public API %% =================================================================== +%% @doc Remove files and directories. +%% Target is a single filename, directoryname or wildcard expression. +%% @spec rm_rf(string()) -> ok +-spec rm_rf(Target::string()) -> ok. rm_rf(Target) -> - [] = os:cmd(?FMT("rm -rf ~s", [Target])), - ok. + case os:type() of + {unix,_} -> + [] = os:cmd(?FMT("rm -rf ~s", [Target])), + ok; + {win32,_} -> + ok = rm_rf_win32(Target) + end. +-spec cp_r(Sources::list(string()), Dest::string()) -> ok. cp_r(Sources, Dest) -> - SourceStr = string:join(Sources, " "), - [] = os:cmd(?FMT("cp -R ~s ~s", [SourceStr, Dest])), - ok. + case os:type() of + {unix,_} -> + SourceStr = string:join(Sources, " "), + [] = os:cmd(?FMT("cp -R ~s ~s", [SourceStr, Dest])), + ok; + {win32,_} -> + lists:foreach(fun(Src) -> ok = cp_r_win32(Src,Dest) end, Sources), + ok + end. delete_each([]) -> ok; @@ -58,3 +74,55 @@ delete_each([File | Rest]) -> ?FAIL end. +%% =================================================================== +%% Internal functions +%% =================================================================== + +rm_rf_win32(Target) -> + Filelist = filelib:wildcard(Target), + Dirs = lists:filter(fun filelib:is_dir/1,Filelist), + Files = lists:subtract(Filelist,Dirs), + ok = delete_each(Files), + ok = delete_each_dir_win32(Dirs), + ok. + +delete_each_dir_win32([]) -> ok; +delete_each_dir_win32([Dir | Rest]) -> + [] = os:cmd(?FMT("rd /q /s ~s", [filename:nativename(Dir)])), + delete_each_dir_win32(Rest). + +xcopy_win32(Source,Dest)-> + R = os:cmd(?FMT("xcopy ~s ~s /q /y /e 2> nul", + [filename:nativename(Source), filename:nativename(Dest)])), + case string:str(R,"\r\n") > 0 of + %% when xcopy fails, stdout is empty and and error message is printed + %% to stderr (which is redirected to nul) + true -> ok; + false -> + {error, lists:flatten( + io_lib:format("Failed to xcopy from ~s to ~s\n", + [Source, Dest]))} + end. + +cp_r_win32({true,SourceDir},{true,DestDir}) -> + % from directory to directory + SourceBase = filename:basename(SourceDir), + ok = case file:make_dir(filename:join(DestDir,SourceBase)) of + {error,eexist} -> ok; + Other -> Other + end, + ok = xcopy_win32(SourceDir,filename:join(DestDir,SourceBase)); +cp_r_win32({false,Source},{true,DestDir}) -> + % from file to directory + cp_r_win32({false,Source}, + {false,filename:join(DestDir,filename:basename(Source))}); +cp_r_win32({false,Source},{false,Dest}) -> + % from file to file + {ok,_} = file:copy(Source,Dest), + ok; +cp_r_win32(Source,Dest) -> + Dst = {filelib:is_dir(Dest),Dest}, + lists:foreach(fun(Src) -> + ok = cp_r_win32({filelib:is_dir(Src),Src},Dst) + end, filelib:wildcard(Source)), + ok. diff --git a/src/rebar_reltool.erl b/src/rebar_reltool.erl index 024870e..b8e1095 100644 --- a/src/rebar_reltool.erl +++ b/src/rebar_reltool.erl @@ -281,7 +281,7 @@ execute_overlay([{copy, In, Out} | Rest], Vars, BaseDir, TargetDir) -> false -> ok = filelib:ensure_dir(OutFile) end, - rebar_utils:sh(?FMT("cp -R ~p ~p", [InFile, OutFile]), []), + rebar_file_utils:cp_r([InFile], OutFile), execute_overlay(Rest, Vars, BaseDir, TargetDir); execute_overlay([{template, In, Out} | Rest], Vars, BaseDir, TargetDir) -> InFile = render(filename:join(BaseDir, In), Vars), |