summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2017-08-17 11:36:02 -0400
committerGitHub <noreply@github.com>2017-08-17 11:36:02 -0400
commit1c5052fb4112e567ffe73af19b8a1f6d80655b28 (patch)
tree186f9ab5bca2fa6bb97d8c87eb8a6edcd7d5be4d
parent3d15c00917db14148d12658c731e71e921cbb4bb (diff)
parent0588936de12fe5b1607c6a23e300904e8f0fc6c0 (diff)
Merge pull request #1603 from ferd/win32-non-ntfs-support
Support Windows with non-NTFS filesystems
-rw-r--r--src/rebar_file_utils.erl42
1 files changed, 35 insertions, 7 deletions
diff --git a/src/rebar_file_utils.erl b/src/rebar_file_utils.erl
index d7716e5..c860513 100644
--- a/src/rebar_file_utils.erl
+++ b/src/rebar_file_utils.erl
@@ -105,7 +105,7 @@ symlink_or_copy(Source, Target) ->
T = unicode:characters_to_list(Target),
case filelib:is_dir(S) of
true ->
- win32_symlink(S, T);
+ win32_symlink_or_copy(S, T);
false ->
cp_r([S], T)
end;
@@ -119,20 +119,48 @@ symlink_or_copy(Source, Target) ->
end
end.
-win32_symlink(Source, Target) ->
+%% @private Compatibility function for windows
+win32_symlink_or_copy(Source, Target) ->
Res = rebar_utils:sh(
?FMT("cmd /c mklink /j \"~ts\" \"~ts\"",
[rebar_utils:escape_double_quotes(filename:nativename(Target)),
rebar_utils:escape_double_quotes(filename:nativename(Source))]),
[{use_stdout, false}, return_on_error]),
- case win32_ok(Res) of
+ case win32_mklink_ok(Res, Target) of
true -> ok;
- false ->
- {error, lists:flatten(
- io_lib:format("Failed to symlink ~ts to ~ts~n",
- [Source, Target]))}
+ false -> cp_r_win32(Source, drop_last_dir_from_path(Target))
end.
+%% @private specifically pattern match against the output
+%% of the windows 'mklink' shell call; different values from
+%% what win32_ok/1 handles
+win32_mklink_ok({ok, _}, _) ->
+ true;
+win32_mklink_ok({error,{1,"Local NTFS volumes are required to complete the operation.\n"}}, _) ->
+ false;
+win32_mklink_ok({error,{1,"Cannot create a file when that file already exists.\n"}}, Target) ->
+ % File or dir is already in place; find if it is already a symlink (true) or
+ % if it is a directory (copy-required; false)
+ is_symlink(Target);
+win32_mklink_ok(_, _) ->
+ false.
+
+%% @private
+is_symlink(Filename) ->
+ {ok, Info} = file:read_link_info(Filename),
+ Info#file_info.type == symlink.
+
+%% @private
+%% drops the last 'node' of the filename, presumably the last dir such as 'src'
+%% this is because cp_r_win32/2 automatically adds the dir name, to appease
+%% robocopy and be more uniform with POSIX
+drop_last_dir_from_path([]) ->
+ [];
+drop_last_dir_from_path(Path) ->
+ case lists:droplast(filename:split(Path)) of
+ [] -> [];
+ Dirs -> filename:join(Dirs)
+ end.
%% @doc Remove files and directories.
%% Target is a single filename, directoryname or wildcard expression.