summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rebar_git_resource.erl67
-rw-r--r--src/rebar_pkg_resource.erl6
-rw-r--r--src/rebar_resource.erl8
-rw-r--r--src/rebar_utils.erl23
4 files changed, 90 insertions, 14 deletions
diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl
index 444163e..a6b60d5 100644
--- a/src/rebar_git_resource.erl
+++ b/src/rebar_git_resource.erl
@@ -6,7 +6,8 @@
-export([lock/2
,download/2
- ,needs_update/2]).
+ ,needs_update/2
+ ,make_vsn/1]).
-include("rebar.hrl").
@@ -79,3 +80,67 @@ download(Dir, {git, Url, Rev}) ->
rebar_utils:sh(?FMT("git clone -n ~s ~s", [Url, filename:basename(Dir)]),
[{cd, filename:dirname(Dir)}]),
rebar_utils:sh(?FMT("git checkout -q ~s", [Rev]), [{cd, Dir}]).
+
+make_vsn(Dir) ->
+ Cwd = file:get_cwd(),
+ try
+ ok = file:set_cwd(Dir),
+ {Vsn, RawRef, RawCount} = collect_default_refcount(),
+ {plain, build_vsn_string(Vsn, RawRef, RawCount)}
+ after
+ file:set_cwd(Cwd)
+ end.
+
+%% Internal functions
+
+collect_default_refcount() ->
+ %% Get the tag timestamp and minimal ref from the system. The
+ %% timestamp is really important from an ordering perspective.
+ RawRef = os:cmd("git log -n 1 --pretty=format:'%h\n' "),
+
+ {Tag, TagVsn} = parse_tags(),
+ RawCount =
+ case Tag of
+ undefined ->
+ os:cmd("git rev-list HEAD | wc -l");
+ _ ->
+ get_patch_count(Tag)
+ end,
+ {TagVsn, RawRef, RawCount}.
+
+build_vsn_string(Vsn, RawRef, RawCount) ->
+ %% Cleanup the tag and the Ref information. Basically leading 'v's and
+ %% whitespace needs to go away.
+ RefTag = case RawRef of
+ undefined ->
+ "";
+ RawRef ->
+ [".ref", re:replace(RawRef, "\\s", "", [global])]
+ end,
+ Count = erlang:iolist_to_binary(re:replace(RawCount, "\\s", "", [global])),
+
+ %% Create the valid [semver](http://semver.org) version from the tag
+ case Count of
+ <<"0">> ->
+ erlang:binary_to_list(erlang:iolist_to_binary(Vsn));
+ _ ->
+ erlang:binary_to_list(erlang:iolist_to_binary([Vsn, "+build.",
+ Count, RefTag]))
+ end.
+
+get_patch_count(RawRef) ->
+ Ref = re:replace(RawRef, "\\s", "", [global]),
+ Cmd = io_lib:format("git rev-list ~s..HEAD | wc -l",
+ [Ref]),
+ os:cmd(Cmd).
+
+parse_tags() ->
+ first_valid_tag(os:cmd("git log --oneline --decorate | fgrep \"tag: \" -1000")).
+
+first_valid_tag(Line) ->
+ case re:run(Line, "(\\(|\\s)tag:\\s(v([^,\\)]+))", [{capture, [2, 3], list}]) of
+ {match,[Tag, Vsn]} ->
+ {Tag, Vsn};
+ nomatch ->
+ {undefined, "0.0.0"}
+ end.
diff --git a/src/rebar_pkg_resource.erl b/src/rebar_pkg_resource.erl
index 1590458..5cd6fc8 100644
--- a/src/rebar_pkg_resource.erl
+++ b/src/rebar_pkg_resource.erl
@@ -6,7 +6,8 @@
-export([lock/2
,download/2
- ,needs_update/2]).
+ ,needs_update/2
+ ,make_vsn/1]).
-include("rebar.hrl").
@@ -26,3 +27,6 @@ download(Dir, {pkg, _Name, _Vsn, Url}) ->
TmpFile = filename:join(Dir, "package.tar.gz"),
{ok, saved_to_file} = httpc:request(get, {binary_to_list(Url), []}, [], [{stream, TmpFile}]),
{tarball, TmpFile}.
+
+make_vsn(_) ->
+ {error, "Replacing version of type pkg not supported."}.
diff --git a/src/rebar_resource.erl b/src/rebar_resource.erl
index f0490f8..04b8d73 100644
--- a/src/rebar_resource.erl
+++ b/src/rebar_resource.erl
@@ -24,16 +24,20 @@
behaviour_info(callbacks) ->
[{lock, 2},
{download, 2},
- {needs_update,2}];
+ {needs_update,2},
+ {make_vsn, 1}];
behaviour_info(_) ->
undefined.
-else.
--callback lock(file:filename_all(), tuple()) -> rebar_resource:resource().
+-callback lock(file:filename_all(), tuple()) ->
+ rebar_resource:resource().
-callback download(file:filename_all(), tuple()) ->
{tarball, file:filename_all()} | {ok, any()} | {error, any()}.
-callback needs_update(file:filename_all(), tuple()) ->
{tarball, file:filename_all()} | {ok, any()} | {error, any()}.
+-callback make_vsn(file:filename_all()) ->
+ {plain, string()} | {error, string()}.
-endif.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 347b02a..4815ad2 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -438,13 +438,15 @@ escript_foldl(Fun, Acc, File) ->
end.
vcs_vsn_1(Vcs, Dir) ->
- case vcs_vsn_cmd(Vcs) of
+ case vcs_vsn_cmd(Vcs, Dir) of
{plain, VsnString} ->
VsnString;
{cmd, CmdString} ->
vcs_vsn_invoke(CmdString, Dir);
unknown ->
?ABORT("vcs_vsn: Unknown vsn format: ~p\n", [Vcs]);
+ {error, Reason} ->
+ ?ABORT("vcs_vsn: ~s\n", [Reason]);
Cmd ->
%% If there is a valid VCS directory in the application directory,
%% use that version info
@@ -471,15 +473,16 @@ vcs_vsn_1(Vcs, Dir) ->
end
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";
-vcs_vsn_cmd(fossil) -> "fossil info";
-vcs_vsn_cmd({cmd, _Cmd}=Custom) -> Custom;
-vcs_vsn_cmd(Version) when is_list(Version) -> {plain, Version};
-vcs_vsn_cmd(_) -> unknown.
+vcs_vsn_cmd(VCS, Dir) when VCS =:= git ; VCS =:= "git" ->
+ rebar_git_resource:make_vsn(Dir);
+vcs_vsn_cmd(VCS, Dir) when VCS =:= pkg ; VCS =:= "pkg" ->
+ rebar_pkg_resource:make_vsn(Dir);
+vcs_vsn_cmd({cmd, _Cmd}=Custom, _) ->
+ Custom;
+vcs_vsn_cmd(Version, _) when is_list(Version) ->
+ {plain, Version};
+vcs_vsn_cmd(_, _) ->
+ unknown.
vcs_vsn_invoke(Cmd, Dir) ->
{ok, VsnString} = rebar_utils:sh(Cmd, [{cd, Dir}, {use_stdout, false}]),