summaryrefslogtreecommitdiff
path: root/src/rebar_file_utils.erl
diff options
context:
space:
mode:
authorJuhani Rankimies <juhani@juranki.com>2010-10-26 07:19:30 +0300
committerDave Smith <dizzyd@dizzyd.com>2010-10-27 11:39:12 -0600
commitfd5ebe69a4d4028908247f6d669eb38254613269 (patch)
treef963d76d95a46fda14d6d491ecdc14cabcdc06c1 /src/rebar_file_utils.erl
parent75fc2378bf006b5660ce2115561d36bea10e04c5 (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/rebar_file_utils.erl')
-rw-r--r--src/rebar_file_utils.erl78
1 files changed, 73 insertions, 5 deletions
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.