diff options
Diffstat (limited to 'bootstrap')
-rwxr-xr-x | bootstrap | 159 |
1 files changed, 132 insertions, 27 deletions
@@ -2,6 +2,7 @@ %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- %% ex: ft=erlang ts=4 sw=4 et + main(_Args) -> %% Fetch and build deps required to build rebar3 BaseDeps = [{providers, []} @@ -26,7 +27,7 @@ main(_Args) -> {ok, State} = rebar3:run(["compile"]), reset_env(), os:putenv("REBAR_PROFILE", ""), - %% Build erlydtl files (a hook on compile in the default profile) and escript file + DepsPaths = rebar_state:code_paths(State, all_deps), code:add_pathsa(DepsPaths), @@ -105,23 +106,124 @@ compile_file(File, Opts) -> bootstrap_rebar3() -> filelib:ensure_dir("_build/default/lib/rebar/ebin/dummy.beam"), code:add_path("_build/default/lib/rebar/ebin/"), - file:make_symlink(filename:absname("src"), filename:absname("_build/default/lib/rebar/src")), + ok = symlink_or_copy(filename:absname("src"), + filename:absname("_build/default/lib/rebar/src")), Sources = ["src/rebar_resource.erl" | filelib:wildcard("src/*.erl")], [compile_file(X, [{outdir, "_build/default/lib/rebar/ebin/"} ,return | additional_defines()]) || X <- Sources], code:add_patha(filename:absname("_build/default/lib/rebar/ebin")). +%%rebar.hrl +-define(FMT(Str, Args), lists:flatten(io_lib:format(Str, Args))). +%%/rebar.hrl +%%rebar_file_utils +symlink_or_copy(Source, Target) -> + Link = case os:type() of + {win32, _} -> + Source; + _ -> + make_relative_path(Source, Target) + end, + case file:make_symlink(Link, Target) of + ok -> + ok; + {error, eexist} -> + ok; + {error, _} -> + cp_r([Source], Target) + end. + +make_relative_path(Source, Target) -> + do_make_relative_path(filename:split(Source), filename:split(Target)). + +do_make_relative_path([H|T1], [H|T2]) -> + do_make_relative_path(T1, T2); +do_make_relative_path(Source, Target) -> + Base = lists:duplicate(max(length(Target) - 1, 0), ".."), + filename:join(Base ++ Source). + +cp_r([], _Dest) -> + ok; +cp_r(Sources, Dest) -> + case os:type() of + {unix, _} -> + EscSources = [escape_path(Src) || Src <- Sources], + SourceStr = string:join(EscSources, " "), + 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. + +xcopy_win32(Source,Dest)-> + R = os:cmd(?FMT("xcopy \"~s\" \"~s\" /q /y /e 2> nul", + [filename:nativename(Source), filename:nativename(Dest)])), + case length(R) > 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} = S,{true, DestDir}) -> + %% from file to directory + cp_r_win32(S, {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({true, SourceDir}, {false, DestDir}) -> + case filelib:is_regular(DestDir) of + true -> + %% From directory to file? This shouldn't happen + {error, lists:flatten( + io_lib:format("Cannot copy dir (~p) to file (~p)\n", + [SourceDir, DestDir]))}; + false -> + %% Specifying a target directory that doesn't currently exist. + %% So let's attempt to create this directory + case filelib:ensure_dir(filename:join(DestDir, "dummy")) of + ok -> + ok = xcopy_win32(SourceDir, DestDir); + {error, Reason} -> + {error, lists:flatten( + io_lib:format("Unable to create dir ~p: ~p\n", + [DestDir, Reason]))} + end + end; +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. + +escape_path(Str) -> + re:replace(Str, "([ ()?])", "\\\\&", [global, {return, list}]). +%%/rebar_file_utils + setup_env() -> - %% We don't need or want erlydtl or relx providers loaded yet + %% We don't need or want relx providers loaded yet application:load(rebar), {ok, Providers} = application:get_env(rebar, providers), - Providers1 = Providers -- [rebar_prv_erlydtl_compiler, - rebar_prv_release, + Providers1 = Providers -- [rebar_prv_release, rebar_prv_tar], application:set_env(rebar, providers, Providers1). reset_env() -> - %% Reset the env so we get all providers and can build erlydtl files + %% Reset the env so we get all providers application:unset_env(rebar, providers), application:unload(rebar), application:load(rebar). @@ -196,25 +298,28 @@ otp_release1([$R,N|_]=Rel) when is_integer(N) -> %% the "\n". otp_release1(Rel) -> File = filename:join([code:root_dir(), "releases", Rel, "OTP_VERSION"]), - {ok, Vsn} = file:read_file(File), - - %% It's fine to rely on the binary module here because we can - %% be sure that it's available when the otp_release string does - %% not begin with $R. - Size = byte_size(Vsn), - %% The shortest vsn string consists of at least two digits - %% followed by "\n". Therefore, it's safe to assume Size >= 3. - case binary:part(Vsn, {Size, -3}) of - <<"**\n">> -> - %% The OTP documentation mentions that a system patched - %% using the otp_patch_apply tool available to licensed - %% customers will leave a '**' suffix in the version as a - %% flag saying the system consists of application versions - %% from multiple OTP versions. We ignore this flag and - %% drop the suffix, given for all intents and purposes, we - %% cannot obtain relevant information from it as far as - %% tooling is concerned. - binary:bin_to_list(Vsn, {0, Size - 3}); - _ -> - binary:bin_to_list(Vsn, {0, Size - 1}) + case file:read_file(File) of + {error, _} -> + Rel; + {ok, Vsn} -> + %% It's fine to rely on the binary module here because we can + %% be sure that it's available when the otp_release string does + %% not begin with $R. + Size = byte_size(Vsn), + %% The shortest vsn string consists of at least two digits + %% followed by "\n". Therefore, it's safe to assume Size >= 3. + case binary:part(Vsn, {Size, -3}) of + <<"**\n">> -> + %% The OTP documentation mentions that a system patched + %% using the otp_patch_apply tool available to licensed + %% customers will leave a '**' suffix in the version as a + %% flag saying the system consists of application versions + %% from multiple OTP versions. We ignore this flag and + %% drop the suffix, given for all intents and purposes, we + %% cannot obtain relevant information from it as far as + %% tooling is concerned. + binary:bin_to_list(Vsn, {0, Size - 3}); + _ -> + binary:bin_to_list(Vsn, {0, Size - 1}) + end end. |