diff options
| -rw-r--r-- | rebar.config.sample | 5 | ||||
| -rw-r--r-- | src/rebar_deps.erl | 49 | ||||
| -rw-r--r-- | src/rebar_utils.erl | 20 | 
3 files changed, 70 insertions, 4 deletions
| diff --git a/rebar.config.sample b/rebar.config.sample index 515ed00..47812c1 100644 --- a/rebar.config.sample +++ b/rebar.config.sample @@ -155,7 +155,7 @@  %% name as an atom, eg. mochiweb, a name and a version (from the .app file), or  %% an application name, a version and the SCM details on how to fetch it (SCM  %% type, location and revision). -%% Rebar currently supports git, hg, bzr, svn, rsync, and fossil. +%% Rebar currently supports git, hg, bzr, svn, rsync, fossil, and p4.  {deps, [app_name,          {rebar, "1.0.*"},          {rebar, ".*", @@ -188,7 +188,8 @@          {app_name, ".*", {svn, "svn://svn.example.org/url"}},          {app_name, ".*", {bzr, "https://www.example.org/url", "Rev"}},          {app_name, ".*", {fossil, "https://www.example.org/url"}}, -        {app_name, ".*", {fossil, "https://www.example.org/url", "Vsn"}}]}. +        {app_name, ".*", {fossil, "https://www.example.org/url", "Vsn"}}, +        {app_name, ".*", {p4, "//depot/subdir/app_dir"}}]}.  %% == Subdirectories == diff --git a/src/rebar_deps.erl b/src/rebar_deps.erl index 43bde04..392882c 100644 --- a/src/rebar_deps.erl +++ b/src/rebar_deps.erl @@ -277,7 +277,8 @@ info_help(Description) ->            {app_name, ".*", {svn, "svn://svn.example.org/url"}},            {app_name, ".*", {bzr, "https://www.example.org/url", "Rev"}},            {app_name, ".*", {fossil, "https://www.example.org/url"}}, -          {app_name, ".*", {fossil, "https://www.example.org/url", "Vsn"}}]} +          {app_name, ".*", {fossil, "https://www.example.org/url", "Vsn"}}, +          {app_name, ".*", {p4, "//depot/subdir/app_dir"}}]}         ]).  %% Added because of trans deps, @@ -507,6 +508,40 @@ use_source(Config, Dep, Count) ->              use_source(Config, Dep#dep { dir = TargetDir }, Count-1)      end. +-record(p4_settings, { +          client=undefined, +          transport="tcp4:perforce:1666", +          username, +          password +         }). +init_p4_settings(Basename) -> +    #p4_settings{client = +                     case inet:gethostname() of +                         {ok,HostName} -> +                             HostName ++ "-" +                                 ++ os:getenv("USER") ++ "-" +                                 ++ Basename +                                 ++ "-Rebar-automated-download" +                     end}. + +download_source(AppDir, {p4, Url}) -> +    download_source(AppDir, {p4, Url, "#head"}); +download_source(AppDir, {p4, Url, Rev}) -> +    download_source(AppDir, {p4, Url, Rev, init_p4_settings(filename:basename(AppDir))}); +download_source(AppDir, {p4, Url, _Rev, Settings}) -> +    ok = filelib:ensure_dir(AppDir), +    rebar_utils:sh_send("p4 client -i", +                   ?FMT("Client: ~s~n" +                        ++"Description: generated by Rebar~n" +                        ++"Root: ~s~n" +                        ++"View:~n" +                        ++"  ~s/...  //~s/...~n", +                        [Settings#p4_settings.client, +                         AppDir, +                         Url, +                         Settings#p4_settings.client]), +                       []), +    rebar_utils:sh(?FMT("p4 -c ~s sync -f", [Settings#p4_settings.client]), []);  download_source(AppDir, {hg, Url, Rev}) ->      ok = filelib:ensure_dir(AppDir),      rebar_utils:sh(?FMT("hg clone -U ~s ~s", [Url, filename:basename(AppDir)]), @@ -573,6 +608,8 @@ update_source(Config, Dep) ->              Dep      end. +update_source1(AppDir, Args) when element(1, Args) =:= p4 -> +    download_source(AppDir, Args);  update_source1(AppDir, {git, Url}) ->      update_source1(AppDir, {git, Url, {branch, "HEAD"}});  update_source1(AppDir, {git, Url, ""}) -> @@ -696,7 +733,7 @@ source_engine_avail(Source) ->  source_engine_avail(Name, Source)    when Name == hg; Name == git; Name == svn; Name == bzr; Name == rsync; -       Name == fossil -> +       Name == fossil; Name == p4 ->      case vcs_client_vsn(Name) >= required_vcs_client_vsn(Name) of          true ->              true; @@ -717,6 +754,7 @@ vcs_client_vsn(Path, VsnArg, VsnRegex) ->              false      end. +required_vcs_client_vsn(p4)     -> {2013, 1};  required_vcs_client_vsn(hg)     -> {1, 1};  required_vcs_client_vsn(git)    -> {1, 5};  required_vcs_client_vsn(bzr)    -> {2, 0}; @@ -724,6 +762,9 @@ required_vcs_client_vsn(svn)    -> {1, 6};  required_vcs_client_vsn(rsync)  -> {2, 0};  required_vcs_client_vsn(fossil) -> {1, 0}. +vcs_client_vsn(p4) -> +    vcs_client_vsn(rebar_utils:find_executable("p4"), " -V", +                   "Rev\\. .*/(\\d+)\\.(\\d)/");  vcs_client_vsn(hg) ->      vcs_client_vsn(rebar_utils:find_executable("hg"), " --version",                     "version (\\d+).(\\d+)"); @@ -743,6 +784,8 @@ vcs_client_vsn(fossil) ->      vcs_client_vsn(rebar_utils:find_executable("fossil"), " version",                     "version (\\d+).(\\d+)"). +has_vcs_dir(p4, _) -> +    true;  has_vcs_dir(git, Dir) ->      filelib:is_dir(filename:join(Dir, ".git"));  has_vcs_dir(hg, Dir) -> @@ -760,6 +803,8 @@ has_vcs_dir(_, _) ->  print_source(#dep{app=App, source=Source}) ->      ?CONSOLE("~s~n", [format_source(App, Source)]). +format_source(App, {p4, Url}) -> +    format_source(App, {p4, Url, "#head"});  format_source(App, {git, Url}) ->      ?FMT("~p BRANCH ~s ~s", [App, "HEAD", Url]);  format_source(App, {git, Url, ""}) -> diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 2d227b6..6b8e874 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -31,6 +31,7 @@           get_arch/0,           wordsize/0,           sh/2, +         sh_send/3,           find_files/2, find_files/3,           now_str/0,           ensure_dir/1, @@ -87,6 +88,24 @@ wordsize() ->              integer_to_list(8 * erlang:system_info(wordsize))      end. +sh_send(Command0, String, Options0) -> +    ?INFO("sh_send info:\n\tcwd: ~p\n\tcmd: ~s < ~s\n", [get_cwd(), Command0, String]), +    ?DEBUG("\topts: ~p\n", [Options0]), + +    DefaultOptions = [use_stdout, abort_on_error], +    Options = [expand_sh_flag(V) +               || V <- proplists:compact(Options0 ++ DefaultOptions)], + +    Command = patch_on_windows(Command0, proplists:get_value(env, Options, [])), +    PortSettings = proplists:get_all_values(port_settings, Options) ++ +        [exit_status, {line, 16384}, use_stdio, stderr_to_stdout, hide], +    Port = open_port({spawn, Command}, PortSettings), + +    %% allow us to send some data to the shell command's STDIN +    %% Erlang doesn't let us get any reply after sending an EOF, though... +    Port ! {self(), {command, String}}, +    port_close(Port). +  %%  %% Options = [Option] -- defaults to [use_stdout, abort_on_error]  %% Option = ErrorOption | OutputOption | {cd, string()} | {env, Env} @@ -478,6 +497,7 @@ vcs_vsn_1(Vcs, Dir) ->      end.  vcs_vsn_cmd(git)    -> "git describe --always --tags"; +vcs_vsn_cmd(p4)     -> "echo #head";  vcs_vsn_cmd(hg)     -> "hg identify -i";  vcs_vsn_cmd(bzr)    -> "bzr revno";  vcs_vsn_cmd(svn)    -> "svnversion"; | 
