Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

224 lignes
8.2 KiB

il y a 15 ans
il y a 15 ans
il y a 13 ans
il y a 15 ans
il y a 15 ans
il y a 13 ans
il y a 15 ans
il y a 15 ans
il y a 13 ans
il y a 14 ans
il y a 14 ans
il y a 14 ans
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. %% -------------------------------------------------------------------
  4. %%
  5. %% rebar: Erlang Build Tools
  6. %%
  7. %% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com)
  8. %%
  9. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  10. %% of this software and associated documentation files (the "Software"), to deal
  11. %% in the Software without restriction, including without limitation the rights
  12. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. %% copies of the Software, and to permit persons to whom the Software is
  14. %% furnished to do so, subject to the following conditions:
  15. %%
  16. %% The above copyright notice and this permission notice shall be included in
  17. %% all copies or substantial portions of the Software.
  18. %%
  19. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. %% THE SOFTWARE.
  26. %% -------------------------------------------------------------------
  27. -module(rebar_file_utils).
  28. -export([rm_rf/1,
  29. cp_r/2,
  30. mv/2,
  31. delete_each/1,
  32. write_file_if_contents_differ/2,
  33. system_tmpdir/0,
  34. system_tmpdir/1,
  35. reset_dir/1]).
  36. -include("rebar.hrl").
  37. %% ===================================================================
  38. %% Public API
  39. %% ===================================================================
  40. %% @doc Remove files and directories.
  41. %% Target is a single filename, directoryname or wildcard expression.
  42. -spec rm_rf(string()) -> 'ok'.
  43. rm_rf(Target) ->
  44. case os:type() of
  45. {unix, _} ->
  46. EscTarget = escape_path(Target),
  47. {ok, []} = rebar_utils:sh(?FMT("rm -rf ~s", [EscTarget]),
  48. [{use_stdout, false}, abort_on_error]),
  49. ok;
  50. {win32, _} ->
  51. Filelist = filelib:wildcard(Target),
  52. Dirs = [F || F <- Filelist, filelib:is_dir(F)],
  53. Files = Filelist -- Dirs,
  54. ok = delete_each(Files),
  55. ok = delete_each_dir_win32(Dirs),
  56. ok
  57. end.
  58. -spec cp_r(list(string()), file:filename()) -> 'ok'.
  59. cp_r([], _Dest) ->
  60. ok;
  61. cp_r(Sources, Dest) ->
  62. case os:type() of
  63. {unix, _} ->
  64. EscSources = [escape_path(Src) || Src <- Sources],
  65. SourceStr = string:join(EscSources, " "),
  66. {ok, []} = rebar_utils:sh(?FMT("cp -R ~s \"~s\"",
  67. [SourceStr, Dest]),
  68. [{use_stdout, false}, abort_on_error]),
  69. ok;
  70. {win32, _} ->
  71. lists:foreach(fun(Src) -> ok = cp_r_win32(Src,Dest) end, Sources),
  72. ok
  73. end.
  74. -spec mv(string(), file:filename()) -> 'ok'.
  75. mv(Source, Dest) ->
  76. case os:type() of
  77. {unix, _} ->
  78. EscSource = escape_path(Source),
  79. EscDest = escape_path(Dest),
  80. {ok, []} = rebar_utils:sh(?FMT("mv ~s ~s", [EscSource, EscDest]),
  81. [{use_stdout, false}, abort_on_error]),
  82. ok;
  83. {win32, _} ->
  84. {ok, R} = rebar_utils:sh(
  85. ?FMT("move /y \"~s\" \"~s\" 1> nul",
  86. [filename:nativename(Source),
  87. filename:nativename(Dest)]),
  88. [{use_stdout, false}, return_on_error]),
  89. case R of
  90. [] ->
  91. ok;
  92. _ ->
  93. {error, lists:flatten(
  94. io_lib:format("Failed to move ~s to ~s~n",
  95. [Source, Dest]))}
  96. end
  97. end.
  98. delete_each([]) ->
  99. ok;
  100. delete_each([File | Rest]) ->
  101. case file:delete(File) of
  102. ok ->
  103. delete_each(Rest);
  104. {error, enoent} ->
  105. delete_each(Rest);
  106. {error, Reason} ->
  107. ?ERROR("Failed to delete file ~s: ~p\n", [File, Reason]),
  108. ?FAIL
  109. end.
  110. write_file_if_contents_differ(Filename, Bytes) ->
  111. ToWrite = iolist_to_binary(Bytes),
  112. case file:read_file(Filename) of
  113. {ok, ToWrite} ->
  114. ok;
  115. {ok, _} ->
  116. file:write_file(Filename, ToWrite);
  117. {error, _} ->
  118. file:write_file(Filename, ToWrite)
  119. end.
  120. %% returns an os appropriate tmpdir given a path
  121. -spec system_tmpdir() -> file:filename().
  122. -spec system_tmpdir(PathComponents) -> file:filename() when
  123. PathComponents :: [file:name()].
  124. system_tmpdir() -> system_tmpdir([]).
  125. system_tmpdir(PathComponents) ->
  126. Tmp = case erlang:system_info(system_architecture) of
  127. "win32" ->
  128. "./tmp";
  129. _SysArch ->
  130. "/tmp"
  131. end,
  132. filename:join([Tmp|PathComponents]).
  133. %% recursively removes a directory and then recreates the same
  134. %% directory but empty
  135. -spec reset_dir(Path) -> ok | {error, Reason} when
  136. Path :: file:name(),
  137. Reason :: file:posix().
  138. reset_dir(Path) ->
  139. %% delete the directory if it exists
  140. _ = ec_file:remove(Path, [recursive]),
  141. %% recreate the directory
  142. filelib:ensure_dir(filename:join([Path, "dummy.beam"])).
  143. %% ===================================================================
  144. %% Internal functions
  145. %% ===================================================================
  146. delete_each_dir_win32([]) -> ok;
  147. delete_each_dir_win32([Dir | Rest]) ->
  148. {ok, []} = rebar_utils:sh(?FMT("rd /q /s \"~s\"",
  149. [filename:nativename(Dir)]),
  150. [{use_stdout, false}, return_on_error]),
  151. delete_each_dir_win32(Rest).
  152. xcopy_win32(Source,Dest)->
  153. {ok, R} = rebar_utils:sh(
  154. ?FMT("xcopy \"~s\" \"~s\" /q /y /e 2> nul",
  155. [filename:nativename(Source), filename:nativename(Dest)]),
  156. [{use_stdout, false}, return_on_error]),
  157. case length(R) > 0 of
  158. %% when xcopy fails, stdout is empty and and error message is printed
  159. %% to stderr (which is redirected to nul)
  160. true -> ok;
  161. false ->
  162. {error, lists:flatten(
  163. io_lib:format("Failed to xcopy from ~s to ~s~n",
  164. [Source, Dest]))}
  165. end.
  166. cp_r_win32({true, SourceDir}, {true, DestDir}) ->
  167. %% from directory to directory
  168. SourceBase = filename:basename(SourceDir),
  169. ok = case file:make_dir(filename:join(DestDir, SourceBase)) of
  170. {error, eexist} -> ok;
  171. Other -> Other
  172. end,
  173. ok = xcopy_win32(SourceDir, filename:join(DestDir, SourceBase));
  174. cp_r_win32({false, Source} = S,{true, DestDir}) ->
  175. %% from file to directory
  176. cp_r_win32(S, {false, filename:join(DestDir, filename:basename(Source))});
  177. cp_r_win32({false, Source},{false, Dest}) ->
  178. %% from file to file
  179. {ok,_} = file:copy(Source, Dest),
  180. ok;
  181. cp_r_win32({true, SourceDir}, {false, DestDir}) ->
  182. case filelib:is_regular(DestDir) of
  183. true ->
  184. %% From directory to file? This shouldn't happen
  185. {error, lists:flatten(
  186. io_lib:format("Cannot copy dir (~p) to file (~p)\n",
  187. [SourceDir, DestDir]))};
  188. false ->
  189. %% Specifying a target directory that doesn't currently exist.
  190. %% So let's attempt to create this directory
  191. case filelib:ensure_dir(filename:join(DestDir, "dummy")) of
  192. ok ->
  193. ok = xcopy_win32(SourceDir, DestDir);
  194. {error, Reason} ->
  195. {error, lists:flatten(
  196. io_lib:format("Unable to create dir ~p: ~p\n",
  197. [DestDir, Reason]))}
  198. end
  199. end;
  200. cp_r_win32(Source,Dest) ->
  201. Dst = {filelib:is_dir(Dest), Dest},
  202. lists:foreach(fun(Src) ->
  203. ok = cp_r_win32({filelib:is_dir(Src), Src}, Dst)
  204. end, filelib:wildcard(Source)),
  205. ok.
  206. escape_path(Str) ->
  207. re:replace(Str, "([ ()?])", "\\\\&", [global, {return, list}]).