Skip to content

Commit

Permalink
Merge pull request #1603 from ferd/win32-non-ntfs-support
Browse files Browse the repository at this point in the history
Support Windows with non-NTFS filesystems
  • Loading branch information
ferd authored Aug 17, 2017
2 parents 3d15c00 + 0588936 commit 1c5052f
Showing 1 changed file with 35 additions and 7 deletions.
42 changes: 35 additions & 7 deletions src/rebar_file_utils.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand Down

0 comments on commit 1c5052f

Please sign in to comment.